@fleetless/sdk 4.0.0 → 4.2.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -1
- package/CONTRIBUTING.md +3 -2
- package/dist/index.cjs +216 -55
- package/dist/index.d.cts +137 -9
- package/dist/index.d.ts +137 -9
- package/dist/index.js +214 -55
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to `@fleetless/sdk`. The format follows Keep a Changelog; the versions follow semver.
|
|
3
|
+
All notable changes to `@fleetless/sdk`. The format follows Keep a Changelog; the versions follow semver. A pull request that changes what a consumer sees adds its entry under `## [Unreleased]`; the release renames that heading to the version.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
Built against `@fleetless/contracts` 5.1.0 (pinned to its pre-release `5.1.0-next.1` until that ships).
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`cancelRejectedDetails`, `CANCEL_RETURN_CODES`, `CancelRejectedDetails` and `CancelReturnCode`** are re-exported, so a caller reads a `cancel_rejected` refusal without depending on `@fleetless/contracts`: `cancelRejectedDetails.parse(error.details).goals`, each goal's `return_code` compared against `CANCEL_RETURN_CODES` (`none`, `rejected`, `unknown_goal_id`, `goal_terminated`), or `null` when that goal's server did not answer.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **`JobOrigin` carries its description in the published types.** It was re-exported as a statement whose JSDoc the bundle dropped, so an editor showed it undescribed; it is now declared as an alias, the way `McpExposure` is.
|
|
16
|
+
|
|
17
|
+
## [4.1.0] — 2026-09-30
|
|
18
|
+
|
|
19
|
+
Built against `@fleetless/contracts` 5.0.0. Two changes to `Job` a consumer's code sees, so the next release is a major.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **`JobOrigin`** is re-exported: the type of `Job.origin`.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **`Job.origin` is required**: `fleetless` for a job the cloud minted from an invocation, `external` for a goal the bridge found running on a published action without having sent it — started by anything else on the robot's ROS graph, or its own goal after the bridge lost the mapping. An external job has no parameters and no starter, and never appears in `jobs.history`. A hand-built `Job` (a test fixture, a mock) now needs the field.
|
|
28
|
+
- **`actions.cancel` is answered by the robot's action server.** It resolves once the server accepted the cancel, with the job usually still `running` — the end arrives as the job's own update. It rejects `cancel_rejected` when the server refused (`ERROR_REJECTED`), with `error.details.goals` listing each goal the cancel reached as `{ job_id, goal_id, return_code }` (`0`–`3`, or `null` when that goal's server did not answer); `bridge_timeout` when the bridge did not answer in time; and with the bridge's own code (e.g. `action_server_lost`) when it could not ask at all. Code that treated a resolved cancel as a stopped goal, or every rejection as "nothing was cancelled", needs to read these apart. Cancelling an `unknown` job cancels every `external` goal on its action.
|
|
29
|
+
- **`JobState` gains `unknown`**: the cloud cannot currently say whether the job is still running — the robot went offline, or its bridge did not report in time. Not terminal: only the robot's bridge moves the job on, to `running` or to how it ended. `lost` is now final. An exhaustive `switch` over `JobState` needs the new case; `services.call` keeps waiting through `unknown`, and `jobs.history` takes `state: 'unknown'`.
|
|
4
30
|
|
|
5
31
|
## [4.0.0] — 2026-09-22
|
|
6
32
|
|
package/CONTRIBUTING.md
CHANGED
|
@@ -93,8 +93,9 @@ tell you what else has to move with it.
|
|
|
93
93
|
|
|
94
94
|
**CI runs on GitHub Actions**, in this repository
|
|
95
95
|
(`.github/workflows/verify.yml`) — the suite, on every push and every pull
|
|
96
|
-
request. `release.yml`
|
|
97
|
-
|
|
96
|
+
request. `release.yml` (the **Release** button) calls that same file on the
|
|
97
|
+
commit it publishes, so a release is never checked by a different pipeline
|
|
98
|
+
than a push.
|
|
98
99
|
|
|
99
100
|
**Your pull request is verified, a fork's included** — the same suite, the
|
|
100
101
|
same file. GitHub holds a first-time contributor's first run until a
|
package/dist/index.cjs
CHANGED
|
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
|
+
CANCEL_RETURN_CODES: () => CANCEL_RETURN_CODES,
|
|
24
25
|
FleetlessError: () => FleetlessError,
|
|
25
26
|
InMemoryTokenStore: () => InMemoryTokenStore,
|
|
26
27
|
SDK_ERROR_CODES: () => SDK_ERROR_CODES,
|
|
28
|
+
cancelRejectedDetails: () => cancelRejectedDetails,
|
|
27
29
|
createClient: () => createClient,
|
|
28
30
|
parameterInvalidDetails: () => parameterInvalidDetails
|
|
29
31
|
});
|
|
@@ -440,7 +442,7 @@ function createAssetsApi(http) {
|
|
|
440
442
|
};
|
|
441
443
|
}
|
|
442
444
|
|
|
443
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
445
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/common.js
|
|
444
446
|
var import_zod = require("zod");
|
|
445
447
|
var SLUG_RULE = "A name is lower-case: it starts with a letter, continues with letters and digits, and joins further words with a single underscore \u2014 `battery_voltage`. Capitals, dashes, dots, spaces, a leading digit and a doubled or trailing underscore are all refused.";
|
|
446
448
|
var slug = import_zod.z.string().min(2).max(63).regex(/^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/, SLUG_RULE);
|
|
@@ -471,7 +473,7 @@ var applyError = import_zod.z.object({
|
|
|
471
473
|
details: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
|
|
472
474
|
});
|
|
473
475
|
|
|
474
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
476
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/mcp.js
|
|
475
477
|
var import_zod2 = require("zod");
|
|
476
478
|
function mcpAppEndpointPath(appIdentifier2) {
|
|
477
479
|
return `/mcp/${appIdentifier2}`;
|
|
@@ -520,10 +522,10 @@ var mcpRolePreviewResponse = import_zod2.z.object({
|
|
|
520
522
|
});
|
|
521
523
|
var MCP_ASSET_LINK_TTL_MS = 15 * 60 * 1e3;
|
|
522
524
|
|
|
523
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
525
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/protocol.js
|
|
524
526
|
var import_zod8 = require("zod");
|
|
525
527
|
|
|
526
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
528
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/assets.js
|
|
527
529
|
var import_zod3 = require("zod");
|
|
528
530
|
var assetKind = import_zod3.z.enum(["urdf", "mesh", "texture"]);
|
|
529
531
|
var asset = import_zod3.z.object({
|
|
@@ -843,10 +845,10 @@ var assetSyncBusyDetails = import_zod3.z.object({
|
|
|
843
845
|
started_at_ms: import_zod3.z.number().int().nonnegative()
|
|
844
846
|
});
|
|
845
847
|
|
|
846
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
848
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/config.js
|
|
847
849
|
var import_zod5 = require("zod");
|
|
848
850
|
|
|
849
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
851
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/alerts.js
|
|
850
852
|
var import_zod4 = require("zod");
|
|
851
853
|
var alertRowCondition = import_zod4.z.discriminatedUnion("kind", [
|
|
852
854
|
import_zod4.z.strictObject({
|
|
@@ -916,7 +918,7 @@ var putDatapointDisplayRequest = import_zod4.z.object({
|
|
|
916
918
|
y_max: import_zod4.z.number().finite().nullable()
|
|
917
919
|
}).strict();
|
|
918
920
|
|
|
919
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
921
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/config.js
|
|
920
922
|
var RTSP_URL_RULE = "The URL has to begin with `rtsp://` or `rtsps://` \u2014 `rtsp://cam-1.plant.local/stream1`. No other scheme is accepted: the bridge opens this with a library that would equally honour `file:`.";
|
|
921
923
|
var MJPEG_URL_RULE = "The URL has to begin with `http://` or `https://` \u2014 `http://cam-1.plant.local/video.mjpg`. No other scheme is accepted: the bridge opens this with a library that would equally serve `file:`.";
|
|
922
924
|
var DEVICE_PATH_RULE = "A capture device is a path under `/dev/`, and the character straight after it is a letter or a digit \u2014 `/dev/video0`, or a stable `/dev/v4l/by-id/...` symlink. Nothing outside `/dev/` is accepted: the string reaches OpenCV, which would as happily open an ordinary file.";
|
|
@@ -2008,7 +2010,7 @@ var configState = import_zod5.z.object({
|
|
|
2008
2010
|
applied_errors: import_zod5.z.array(applyError).nullable()
|
|
2009
2011
|
});
|
|
2010
2012
|
|
|
2011
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
2013
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/introspection.js
|
|
2012
2014
|
var import_zod6 = require("zod");
|
|
2013
2015
|
var rosGraphEntry = import_zod6.z.object({
|
|
2014
2016
|
name: rosName,
|
|
@@ -2047,9 +2049,11 @@ var typeDefinition = import_zod6.z.discriminatedUnion("kind", [
|
|
|
2047
2049
|
})
|
|
2048
2050
|
]);
|
|
2049
2051
|
|
|
2050
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
2052
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/jobs.js
|
|
2051
2053
|
var import_zod7 = require("zod");
|
|
2052
|
-
var jobState = import_zod7.z.enum(["running", "succeeded", "failed", "cancelled", "lost"]);
|
|
2054
|
+
var jobState = import_zod7.z.enum(["running", "unknown", "succeeded", "failed", "cancelled", "lost"]);
|
|
2055
|
+
var reportedJobState = jobState.exclude(["unknown"]);
|
|
2056
|
+
var jobOrigin = import_zod7.z.enum(["fleetless", "external"]);
|
|
2053
2057
|
var job = import_zod7.z.object({
|
|
2054
2058
|
id: import_zod7.z.uuid().meta({
|
|
2055
2059
|
description: "The job's id, minted by the cloud when the invocation is accepted. Informative \u2014 state is observed by slug; a cancel names this id to stop one specific job rather than whatever is running."
|
|
@@ -2059,7 +2063,10 @@ var job = import_zod7.z.object({
|
|
|
2059
2063
|
description: "The action or service this job is running, as the published configuration exposes it. One slug carries one job at a time, so every observer of that slug sees the same one."
|
|
2060
2064
|
}),
|
|
2061
2065
|
state: jobState.meta({
|
|
2062
|
-
description: "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `
|
|
2066
|
+
description: "Where the job stands: `running`, `unknown`, `succeeded`, `failed`, `cancelled` or `lost`. `unknown` is not an outcome \u2014 the robot went offline or silent and the cloud does not know yet; the slug stays occupied and the bridge's next statement resolves it, `error` naming why the cloud lost sight of it. `lost` is final: the bridge stated it does not know the job and nothing else runs on its action, or the action server vanished mid-goal."
|
|
2067
|
+
}),
|
|
2068
|
+
origin: jobOrigin.meta({
|
|
2069
|
+
description: "Who started this job. `fleetless` for everything minted by the cloud; `external` for a goal the bridge found active on a published action without having sent it \u2014 no parameters, no starter, never written to `job_runs`."
|
|
2063
2070
|
}),
|
|
2064
2071
|
started_at: import_zod7.z.iso.datetime().meta({
|
|
2065
2072
|
description: "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge, this is **adoption time**, not the real start \u2014 the cloud never minted it."
|
|
@@ -2078,7 +2085,7 @@ var job = import_zod7.z.object({
|
|
|
2078
2085
|
* exists for the same reason on the audit log.
|
|
2079
2086
|
*
|
|
2080
2087
|
* **Scoped honestly: per cloud process, per run.** Job state lives in memory
|
|
2081
|
-
* — that is why `lost`
|
|
2088
|
+
* — that is why `unknown` and `lost` exist at all — so this counter restarts when
|
|
2082
2089
|
* the cloud does, alongside the jobs it orders. Sound, because it only ever
|
|
2083
2090
|
* orders jobs that coexist in one registry — and stated, because a reader
|
|
2084
2091
|
* who assumed `auditEvent.seq`'s durable semantics would be wrong.
|
|
@@ -2113,7 +2120,7 @@ var job = import_zod7.z.object({
|
|
|
2113
2120
|
description: "The structured payload belonging to `code`, for the codes that document one \u2014 `job_queue_full` carries its `limit` and its `queued` count here. Absent for a failure with nothing structured to add, which is most of them."
|
|
2114
2121
|
})
|
|
2115
2122
|
}).nullable().meta({
|
|
2116
|
-
description: "Why the job failed: a human `message`, a `code` where one exists, and `details` for the codes that carry a documented payload. `
|
|
2123
|
+
description: "Why the job failed, or why the cloud does not know how it stands: a human `message`, a `code` where one exists, and `details` for the codes that carry a documented payload. Set on `failed` and `lost`, and on `unknown` \u2014 where `code` is `bridge_disconnected` or `bridge_timeout`, the cloud's own reason for not knowing, cleared when the bridge reports the job running again."
|
|
2117
2124
|
})
|
|
2118
2125
|
});
|
|
2119
2126
|
var jobEvent = import_zod7.z.object({
|
|
@@ -2172,16 +2179,16 @@ var jobRun = import_zod7.z.object({
|
|
|
2172
2179
|
description: "Whether the slug was an `action` or a `service`."
|
|
2173
2180
|
}),
|
|
2174
2181
|
state: jobState.meta({
|
|
2175
|
-
description: "How the run ended, or `running` while it is still going. `lost`
|
|
2182
|
+
description: "How the run ended, or `running` while it is still going. `unknown` while the robot has not accounted for it \u2014 offline or silent \u2014 and updated once the bridge says how it stands. `lost` is final: the bridge did not know the run and nothing else ran on its action, so the outcome is unknowable rather than unknown."
|
|
2176
2183
|
}),
|
|
2177
2184
|
started_at: import_zod7.z.iso.datetime().meta({
|
|
2178
2185
|
description: "When the run started, as an ISO 8601 timestamp. Runs are listed and filtered by this instant."
|
|
2179
2186
|
}),
|
|
2180
2187
|
ended_at: import_zod7.z.iso.datetime().nullable().meta({
|
|
2181
|
-
description: "When the run finished, as an ISO 8601 timestamp. `null` while it is still `running` \u2014 a run has an end only once it has one."
|
|
2188
|
+
description: "When the run finished, as an ISO 8601 timestamp. `null` while it is still `running` or `unknown` \u2014 a run has an end only once it has one."
|
|
2182
2189
|
}),
|
|
2183
2190
|
duration_ms: import_zod7.z.number().int().nonnegative().nullable().meta({
|
|
2184
|
-
description: 'How long the run took, in milliseconds. `null` while it is still `running`, never `0` standing in for "nothing so far".'
|
|
2191
|
+
description: 'How long the run took, in milliseconds. `null` while it is still `running` or `unknown`, never `0` standing in for "nothing so far".'
|
|
2185
2192
|
}),
|
|
2186
2193
|
result: import_zod7.z.unknown().nullable().meta({
|
|
2187
2194
|
description: "What the action or service returned once it succeeded, shaped by ROS itself. `null` otherwise."
|
|
@@ -2231,7 +2238,7 @@ var jobRunQuery = import_zod7.z.object({
|
|
|
2231
2238
|
description: "Only runs of this action or service."
|
|
2232
2239
|
}),
|
|
2233
2240
|
state: jobState.optional().meta({
|
|
2234
|
-
description: "Only runs in this state \u2014 `running`, `succeeded`, `failed`, `cancelled` or `lost`."
|
|
2241
|
+
description: "Only runs in this state \u2014 `running`, `unknown`, `succeeded`, `failed`, `cancelled` or `lost`."
|
|
2235
2242
|
}),
|
|
2236
2243
|
kind: jobRunKind.optional().meta({
|
|
2237
2244
|
description: "Only `action` runs, or only `service` runs."
|
|
@@ -2265,14 +2272,14 @@ var jobRunSummary = import_zod7.z.object({
|
|
|
2265
2272
|
since_ms: import_zod7.z.number().int().nonnegative()
|
|
2266
2273
|
});
|
|
2267
2274
|
|
|
2268
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
2275
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/protocol.js
|
|
2269
2276
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
2270
2277
|
var MAX_PATIENCE_MS = 12e4;
|
|
2271
2278
|
var MIN_PATIENCE_MS = 1e3;
|
|
2272
2279
|
var activeJob = import_zod8.z.object({
|
|
2273
2280
|
job_id: import_zod8.z.uuid(),
|
|
2274
2281
|
slug,
|
|
2275
|
-
state:
|
|
2282
|
+
state: reportedJobState
|
|
2276
2283
|
});
|
|
2277
2284
|
var bridgeHello = import_zod8.z.object({
|
|
2278
2285
|
type: import_zod8.z.literal("hello"),
|
|
@@ -2283,16 +2290,14 @@ var bridgeHello = import_zod8.z.object({
|
|
|
2283
2290
|
* Every job this bridge still knows about, right now.
|
|
2284
2291
|
*
|
|
2285
2292
|
* A reconnect and a restart look **identical** on the wire — same token,
|
|
2286
|
-
* same version, same frame —
|
|
2287
|
-
*
|
|
2288
|
-
*
|
|
2289
|
-
*
|
|
2290
|
-
*
|
|
2291
|
-
*
|
|
2292
|
-
*
|
|
2293
|
-
*
|
|
2294
|
-
* the cloud needs. A breadcrumb file would only add a window in which the
|
|
2295
|
-
* crash beat the write.
|
|
2293
|
+
* same version, same frame — so the bridge enumerates what it still has:
|
|
2294
|
+
* its live jobs, and after a restart every job whose goal it recognised
|
|
2295
|
+
* again from its persisted job-to-goal mapping. A job the cloud holds
|
|
2296
|
+
* `running` or `unknown` that is *not* named here is "not known to the
|
|
2297
|
+
* bridge"; it becomes `lost` (`job_unknown_to_bridge`) only once the
|
|
2298
|
+
* bridge's goal reports show its action free of goals it cannot
|
|
2299
|
+
* attribute — one of those may be that very job — and at once for a
|
|
2300
|
+
* service job, which has no goals to look at.
|
|
2296
2301
|
*
|
|
2297
2302
|
* Defaulted, so a bridge that sends no such field still parses; no jobs
|
|
2298
2303
|
* and no report both mean the same thing to the cloud: nothing to keep
|
|
@@ -2398,9 +2403,28 @@ var cloudInvoke = import_zod8.z.object({
|
|
|
2398
2403
|
});
|
|
2399
2404
|
var cloudCancel = import_zod8.z.object({
|
|
2400
2405
|
type: import_zod8.z.literal("cancel"),
|
|
2406
|
+
request_id: import_zod8.z.string().min(1).max(64),
|
|
2401
2407
|
slug,
|
|
2402
2408
|
job_id: import_zod8.z.uuid().nullable()
|
|
2403
2409
|
});
|
|
2410
|
+
var CANCEL_RETURN_CODES = { none: 0, rejected: 1, unknown_goal_id: 2, goal_terminated: 3 };
|
|
2411
|
+
var cancelReturnCode = import_zod8.z.number().int().min(0).max(3);
|
|
2412
|
+
var bridgeCancelResultEntry = import_zod8.z.object({
|
|
2413
|
+
/** The job the goal belongs to — the bridge's own, or an external goal's derived id. */
|
|
2414
|
+
job_id: import_zod8.z.uuid(),
|
|
2415
|
+
/** The ROS 2 goal id the cancel was sent for. */
|
|
2416
|
+
goal_id: import_zod8.z.string().min(1),
|
|
2417
|
+
/** `null` when the action server did not answer the cancel request within the bridge's own bound. */
|
|
2418
|
+
return_code: cancelReturnCode.nullable()
|
|
2419
|
+
});
|
|
2420
|
+
var bridgeCancelResult = import_zod8.z.object({
|
|
2421
|
+
type: import_zod8.z.literal("cancel_result"),
|
|
2422
|
+
request_id: import_zod8.z.string().min(1).max(64),
|
|
2423
|
+
slug,
|
|
2424
|
+
goals: import_zod8.z.array(bridgeCancelResultEntry),
|
|
2425
|
+
/** Set when the bridge could not send the cancel at all (no such slug, a service, the server gone). */
|
|
2426
|
+
error: import_zod8.z.object({ code: import_zod8.z.string().min(1), message: import_zod8.z.string().min(1) }).nullable()
|
|
2427
|
+
});
|
|
2404
2428
|
var cloudPublish = import_zod8.z.object({
|
|
2405
2429
|
type: import_zod8.z.literal("publish"),
|
|
2406
2430
|
slug,
|
|
@@ -2420,7 +2444,11 @@ var bridgeJobUpdate = import_zod8.z.object({
|
|
|
2420
2444
|
type: import_zod8.z.literal("job_update"),
|
|
2421
2445
|
job_id: import_zod8.z.uuid(),
|
|
2422
2446
|
slug,
|
|
2423
|
-
|
|
2447
|
+
/** Never `unknown`: that is the cloud's word for not having heard. */
|
|
2448
|
+
state: reportedJobState,
|
|
2449
|
+
origin: jobOrigin,
|
|
2450
|
+
/** The ROS 2 goal id; `null` for a service job, which has no goal. */
|
|
2451
|
+
goal_id: import_zod8.z.string().min(1).nullable(),
|
|
2424
2452
|
feedback: import_zod8.z.unknown().nullable(),
|
|
2425
2453
|
progress: import_zod8.z.number().min(0).max(1).nullable(),
|
|
2426
2454
|
result: import_zod8.z.unknown().nullable(),
|
|
@@ -2430,7 +2458,29 @@ var bridgeJobUpdate = import_zod8.z.object({
|
|
|
2430
2458
|
});
|
|
2431
2459
|
var bridgeJobLost = import_zod8.z.object({
|
|
2432
2460
|
type: import_zod8.z.literal("job_lost"),
|
|
2433
|
-
job_ids: import_zod8.z.array(import_zod8.z.uuid())
|
|
2461
|
+
job_ids: import_zod8.z.array(import_zod8.z.uuid()),
|
|
2462
|
+
error: import_zod8.z.object({ code: import_zod8.z.string().min(1), message: import_zod8.z.string().min(1) }).optional()
|
|
2463
|
+
});
|
|
2464
|
+
var cloudJobQuery = import_zod8.z.object({
|
|
2465
|
+
type: import_zod8.z.literal("job_query"),
|
|
2466
|
+
request_id: import_zod8.z.string().min(1).max(64),
|
|
2467
|
+
job_ids: import_zod8.z.array(import_zod8.z.uuid()).min(1)
|
|
2468
|
+
});
|
|
2469
|
+
var bridgeJobStatusEntry = import_zod8.z.object({
|
|
2470
|
+
job_id: import_zod8.z.uuid(),
|
|
2471
|
+
/** Never `unknown` — the bridge only ever states a definite fact about a job it recognises. */
|
|
2472
|
+
state: reportedJobState,
|
|
2473
|
+
feedback: import_zod8.z.unknown().nullable(),
|
|
2474
|
+
progress: import_zod8.z.number().min(0).max(1).nullable(),
|
|
2475
|
+
result: import_zod8.z.unknown().nullable(),
|
|
2476
|
+
/** Same shape as `job.error`, `details` included — see `jobs.ts`. */
|
|
2477
|
+
error: import_zod8.z.object({ code: import_zod8.z.string().min(1), message: import_zod8.z.string().min(1), details: import_zod8.z.unknown().optional() }).nullable()
|
|
2478
|
+
});
|
|
2479
|
+
var bridgeJobStatus = import_zod8.z.object({
|
|
2480
|
+
type: import_zod8.z.literal("job_status"),
|
|
2481
|
+
request_id: import_zod8.z.string().min(1).max(64),
|
|
2482
|
+
jobs: import_zod8.z.array(bridgeJobStatusEntry),
|
|
2483
|
+
unknown_job_ids: import_zod8.z.array(import_zod8.z.uuid())
|
|
2434
2484
|
});
|
|
2435
2485
|
var cloudIntrospectRequest = import_zod8.z.object({
|
|
2436
2486
|
type: import_zod8.z.literal("introspect_request"),
|
|
@@ -2619,11 +2669,11 @@ var bridgeCameraState = import_zod8.z.object({
|
|
|
2619
2669
|
request_id: import_zod8.z.string().min(1).max(64).nullable()
|
|
2620
2670
|
});
|
|
2621
2671
|
|
|
2622
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
2672
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/config-issues.js
|
|
2623
2673
|
var EXPOSURE_SECTIONS = ["datapoints", "actions", "services", "publishers", "cameras"];
|
|
2624
2674
|
var EXPOSURE_SECTION_NAMES = new Set(EXPOSURE_SECTIONS);
|
|
2625
2675
|
|
|
2626
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
2676
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/rest.js
|
|
2627
2677
|
var import_zod9 = require("zod");
|
|
2628
2678
|
var robot = import_zod9.z.object({
|
|
2629
2679
|
id: import_zod9.z.uuid().meta({
|
|
@@ -3388,13 +3438,13 @@ var slugUsageResponse = import_zod9.z.object({
|
|
|
3388
3438
|
alert_count: import_zod9.z.number().int().nonnegative()
|
|
3389
3439
|
});
|
|
3390
3440
|
|
|
3391
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
3441
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/realtime.js
|
|
3392
3442
|
var import_zod14 = require("zod");
|
|
3393
3443
|
|
|
3394
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
3444
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/client-auth.js
|
|
3395
3445
|
var import_zod13 = require("zod");
|
|
3396
3446
|
|
|
3397
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
3447
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/apps.js
|
|
3398
3448
|
var import_zod10 = require("zod");
|
|
3399
3449
|
var appIdentifier = slug;
|
|
3400
3450
|
var app = import_zod10.z.object({
|
|
@@ -3454,6 +3504,26 @@ var appListResponse = import_zod10.z.object({
|
|
|
3454
3504
|
description: "Every app of the caller's organisation, oldest first by `created_at`. The org scope is the whole filter \u2014 there is no id to narrow by and nothing to refuse."
|
|
3455
3505
|
})
|
|
3456
3506
|
});
|
|
3507
|
+
var appDeletionSummary = import_zod10.z.object({
|
|
3508
|
+
user_count: import_zod10.z.number().int().nonnegative().meta({
|
|
3509
|
+
description: "App users deleted with the app. They are the developer's own customers, not Fleetless users, and exist in no other app."
|
|
3510
|
+
}),
|
|
3511
|
+
role_count: import_zod10.z.number().int().nonnegative().meta({
|
|
3512
|
+
description: "Roles deleted with the app, each with its per-robot slug grants."
|
|
3513
|
+
}),
|
|
3514
|
+
server_key_count: import_zod10.z.number().int().nonnegative().meta({
|
|
3515
|
+
description: "Server keys deleted with the app. A client still holding one is refused at its next request."
|
|
3516
|
+
}),
|
|
3517
|
+
invitation_count: import_zod10.z.number().int().nonnegative().meta({
|
|
3518
|
+
description: "Outstanding invitations \u2014 unspent and unexpired \u2014 that will never be accepted."
|
|
3519
|
+
}),
|
|
3520
|
+
oidc_provider_count: import_zod10.z.number().int().nonnegative().meta({
|
|
3521
|
+
description: "Identity providers configured for this app. The providers themselves are somebody else's; only this app's configuration of them goes."
|
|
3522
|
+
}),
|
|
3523
|
+
mail_template_count: import_zod10.z.number().int().nonnegative().meta({
|
|
3524
|
+
description: "Custom mail templates, of at most three. A kind using the Fleetless default text is not counted \u2014 there is no row to lose."
|
|
3525
|
+
})
|
|
3526
|
+
});
|
|
3457
3527
|
var createAppRequest = import_zod10.z.object({
|
|
3458
3528
|
name: import_zod10.z.string().min(1).max(120),
|
|
3459
3529
|
identifier: appIdentifier,
|
|
@@ -3576,10 +3646,10 @@ var rolePermissions = import_zod10.z.object({
|
|
|
3576
3646
|
})
|
|
3577
3647
|
});
|
|
3578
3648
|
|
|
3579
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
3649
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/app-users.js
|
|
3580
3650
|
var import_zod12 = require("zod");
|
|
3581
3651
|
|
|
3582
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
3652
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/identity.js
|
|
3583
3653
|
var import_zod11 = require("zod");
|
|
3584
3654
|
var password = import_zod11.z.string().min(12).max(256);
|
|
3585
3655
|
var USER_DISPLAY_NAME_MAX = 120;
|
|
@@ -3741,7 +3811,7 @@ var authMeResponse = import_zod11.z.object({ org, user: fleetlessUser });
|
|
|
3741
3811
|
var patchOrgRequest = import_zod11.z.object({ name: import_zod11.z.string().min(1).max(120) }).strict();
|
|
3742
3812
|
var patchAuthMeRequest = import_zod11.z.object({ display_name: import_zod11.z.string().min(1).max(USER_DISPLAY_NAME_MAX).nullable() }).strict();
|
|
3743
3813
|
|
|
3744
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
3814
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/app-users.js
|
|
3745
3815
|
var APP_USER_DISPLAY_NAME_MAX = 120;
|
|
3746
3816
|
var providerSlug = import_zod12.z.string().max(40).regex(/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/, "must be lowercase and hyphen-separated, starting with a letter");
|
|
3747
3817
|
var appUserStatus = import_zod12.z.enum(["pending_verification", "active", "blocked"]);
|
|
@@ -3960,7 +4030,9 @@ var appAuthConfig = import_zod12.z.object({
|
|
|
3960
4030
|
}),
|
|
3961
4031
|
updated_at: import_zod12.z.iso.datetime().meta({ description: "When the configuration was last written, as an ISO 8601 timestamp." })
|
|
3962
4032
|
});
|
|
3963
|
-
var
|
|
4033
|
+
var putAppAuthRegistrationRequest = appAuthConfig.pick({ self_registration: true, allowed_domains: true, allowed_origins: true }).strict();
|
|
4034
|
+
var putAppAuthUrlsRequest = appAuthConfig.pick({ invite_url: true, verify_url: true, reset_url: true }).strict();
|
|
4035
|
+
var putAppAuthMcpRequest = appAuthConfig.pick({ mcp_enabled: true, mcp_login_url: true }).strict();
|
|
3964
4036
|
var mailTemplateKind = import_zod12.z.enum(["invite", "verify", "reset"]);
|
|
3965
4037
|
var appMailTemplate = import_zod12.z.object({
|
|
3966
4038
|
kind: mailTemplateKind.meta({ description: "Which of the three mails this template replaces." }),
|
|
@@ -3992,7 +4064,7 @@ var mailOutcome = import_zod12.z.object({
|
|
|
3992
4064
|
})
|
|
3993
4065
|
});
|
|
3994
4066
|
|
|
3995
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4067
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/client-auth.js
|
|
3996
4068
|
var clientLoginRequest = import_zod13.z.object({
|
|
3997
4069
|
app_identifier: appIdentifier.meta({
|
|
3998
4070
|
description: "The app being logged in to: its globally unique, lowercase, underscore-separated identifier, chosen by the developer at creation. There is no organisation context at login, so this is what decides which app the credentials are checked for."
|
|
@@ -4181,7 +4253,7 @@ var clientIdentity = import_zod13.z.object({
|
|
|
4181
4253
|
})
|
|
4182
4254
|
});
|
|
4183
4255
|
|
|
4184
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4256
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/realtime.js
|
|
4185
4257
|
var clientAuth = import_zod14.z.object({
|
|
4186
4258
|
type: import_zod14.z.literal("auth"),
|
|
4187
4259
|
token: import_zod14.z.string().min(1)
|
|
@@ -4459,7 +4531,7 @@ var orgEventDropped = import_zod14.z.object({
|
|
|
4459
4531
|
dropped: import_zod14.z.number().int().positive()
|
|
4460
4532
|
}).strict();
|
|
4461
4533
|
|
|
4462
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4534
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/client-robots.js
|
|
4463
4535
|
var import_zod15 = require("zod");
|
|
4464
4536
|
var clientRobotListItem = import_zod15.z.object({
|
|
4465
4537
|
...robot.shape,
|
|
@@ -4476,7 +4548,7 @@ var clientRobotListResponse = import_zod15.z.object({
|
|
|
4476
4548
|
})
|
|
4477
4549
|
});
|
|
4478
4550
|
|
|
4479
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4551
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/audit.js
|
|
4480
4552
|
var import_zod16 = require("zod");
|
|
4481
4553
|
var auditActor = import_zod16.z.object({
|
|
4482
4554
|
kind: import_zod16.z.enum(["developer", "end_user", "app_user", "server_key", "bridge"]),
|
|
@@ -4606,7 +4678,7 @@ var auditListResponse = import_zod16.z.object({
|
|
|
4606
4678
|
next_cursor: import_zod16.z.number().int().positive().nullable()
|
|
4607
4679
|
});
|
|
4608
4680
|
|
|
4609
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4681
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/errors.js
|
|
4610
4682
|
var import_zod17 = require("zod");
|
|
4611
4683
|
var apiError = import_zod17.z.object({
|
|
4612
4684
|
code: import_zod17.z.string().min(1),
|
|
@@ -4622,8 +4694,11 @@ var parameterViolation = import_zod17.z.object({
|
|
|
4622
4694
|
var parameterInvalidDetails = import_zod17.z.object({
|
|
4623
4695
|
violations: import_zod17.z.array(parameterViolation).min(1)
|
|
4624
4696
|
});
|
|
4697
|
+
var cancelRejectedDetails = import_zod17.z.object({
|
|
4698
|
+
goals: import_zod17.z.array(bridgeCancelResultEntry).min(1)
|
|
4699
|
+
});
|
|
4625
4700
|
|
|
4626
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4701
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/oauth.js
|
|
4627
4702
|
var import_zod18 = require("zod");
|
|
4628
4703
|
var oauthErrorCode = import_zod18.z.enum([
|
|
4629
4704
|
"invalid_request",
|
|
@@ -4863,7 +4938,7 @@ var oauthAuthorizeQuery = import_zod18.z.object({
|
|
|
4863
4938
|
description: "The authorization request an MCP client sends, per RFC 6749 \xA74.1.1 with mandatory PKCE. The handler reads it parameter by parameter rather than through one parse, because the answers differ: `client_id` and `redirect_uri` are refused flat, with no redirect, since until both are confirmed there is no trusted target to bounce a browser to, and everything after them is reported to the client's own callback as query parameters."
|
|
4864
4939
|
});
|
|
4865
4940
|
|
|
4866
|
-
// node_modules/.pnpm/@fleetless+contracts@
|
|
4941
|
+
// node_modules/.pnpm/@fleetless+contracts@5.1.0-next.1/node_modules/@fleetless/contracts/dist/routes.js
|
|
4867
4942
|
var MCP_APP = MCP_APP_PATHS(":appIdentifier");
|
|
4868
4943
|
var APP_IDENTIFIER = {
|
|
4869
4944
|
name: "appIdentifier",
|
|
@@ -5233,6 +5308,42 @@ var ROUTES = [
|
|
|
5233
5308
|
transport: "http",
|
|
5234
5309
|
notes: "A `default_role_id` naming a role of another app is refused: it is the one cross-app authorization check this shape can carry. Changing the robot set closes every live subscription the app's users hold, since a grant may no longer name a reachable robot."
|
|
5235
5310
|
},
|
|
5311
|
+
{
|
|
5312
|
+
method: "GET",
|
|
5313
|
+
path: "/api/apps/:id/deletion-preview",
|
|
5314
|
+
section: "apps",
|
|
5315
|
+
summary: "Reports what deleting the app would destroy, without destroying it.",
|
|
5316
|
+
audience: "developer",
|
|
5317
|
+
auth: "developer",
|
|
5318
|
+
rateLimited: false,
|
|
5319
|
+
ownerTier: false,
|
|
5320
|
+
status: 200,
|
|
5321
|
+
params: [{ name: "id", description: "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`." }],
|
|
5322
|
+
query: null,
|
|
5323
|
+
request: null,
|
|
5324
|
+
response: appDeletionSummary,
|
|
5325
|
+
errors: [...DEVELOPER_GUARD, "invalid_uuid", "not_found"],
|
|
5326
|
+
transport: "http",
|
|
5327
|
+
notes: "The same shape the delete's own audit event carries, computed by the same function on purpose: the confirmation dialog and the eventual receipt agree by construction, and any difference between them is real drift rather than two estimates that quietly disagree. \n\n**No `force` parameter, unlike the robot pair this is modelled on.** A robot's open live session is a single nameable state whose interruption is its own hazard, which is why that route makes the caller pass `force` explicitly. An app has no equivalent state to force past, and inventing one would be a guess wearing a guard's clothes \u2014 this preview is the guard."
|
|
5328
|
+
},
|
|
5329
|
+
{
|
|
5330
|
+
method: "DELETE",
|
|
5331
|
+
path: "/api/apps/:id",
|
|
5332
|
+
section: "apps",
|
|
5333
|
+
summary: "Deletes an app and everything it produced.",
|
|
5334
|
+
audience: "developer",
|
|
5335
|
+
auth: "developer",
|
|
5336
|
+
rateLimited: false,
|
|
5337
|
+
ownerTier: true,
|
|
5338
|
+
status: 204,
|
|
5339
|
+
params: [{ name: "id", description: "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`." }],
|
|
5340
|
+
query: null,
|
|
5341
|
+
request: null,
|
|
5342
|
+
response: null,
|
|
5343
|
+
errors: [...DEVELOPER_GUARD, "tier_required", "invalid_uuid", "not_found"],
|
|
5344
|
+
transport: "http",
|
|
5345
|
+
notes: "Owner tier, and the gate runs **after** the org-scoped lookup: a developer-tier admin therefore sees the same `404` a stranger would for an app outside their org, rather than a tier refusal that confirms the id exists. A full cascade \u2014 its users, roles, server keys, invitations, OIDC provider configuration and mail templates all go, recorded once as `app.deleted` carrying an `appDeletionSummary`. Its robots are untouched: they belong to the org, not to the app. \n\n**No `force` parameter** \u2014 see `GET /api/apps/:id/deletion-preview`."
|
|
5346
|
+
},
|
|
5236
5347
|
{
|
|
5237
5348
|
method: "POST",
|
|
5238
5349
|
path: "/api/apps/:id/roles",
|
|
@@ -5739,13 +5850,31 @@ var ROUTES = [
|
|
|
5739
5850
|
response: appAuthConfig,
|
|
5740
5851
|
errors: [...DEVELOPER_GUARD, "invalid_uuid", "not_found"],
|
|
5741
5852
|
transport: "http",
|
|
5742
|
-
notes: "One row per app, created with the app and never absent \u2014 an app that has configured nothing reads back the defaults rather than a `404`. `oidc_callback_url` is in the answer and not in the request: it is minted by the cloud from its own public base URL, is the same for every app and every provider, and is the value a developer registers at their identity provider."
|
|
5853
|
+
notes: "One row per app, created with the app and never absent \u2014 an app that has configured nothing reads back the defaults rather than a `404`. `oidc_callback_url` is in the answer and not in the request: it is minted by the cloud from its own public base URL, is the same for every app and every provider, and is the value a developer registers at their identity provider. It stays read-only on every slice write below for a second reason: a writable callback URL would let a caller point the return leg of an OIDC sign-in, which carries an authorization code, at a host they own. `updated_at` is read-only for a duller one: the server stamps it on every write, and a client-supplied value would be a lie about when the row last changed."
|
|
5743
5854
|
},
|
|
5744
5855
|
{
|
|
5745
5856
|
method: "PUT",
|
|
5746
|
-
path: "/api/apps/:id/auth-config",
|
|
5857
|
+
path: "/api/apps/:id/auth-config/registration",
|
|
5858
|
+
section: "apps",
|
|
5859
|
+
summary: "Replaces who may self-register, and from where.",
|
|
5860
|
+
audience: "developer",
|
|
5861
|
+
auth: "developer",
|
|
5862
|
+
rateLimited: false,
|
|
5863
|
+
ownerTier: false,
|
|
5864
|
+
status: 200,
|
|
5865
|
+
params: [{ name: "id", description: "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`." }],
|
|
5866
|
+
query: null,
|
|
5867
|
+
request: putAppAuthRegistrationRequest,
|
|
5868
|
+
response: appAuthConfig,
|
|
5869
|
+
errors: [...DEVELOPER_GUARD, "invalid_uuid", "validation_error", "not_found"],
|
|
5870
|
+
transport: "http",
|
|
5871
|
+
notes: "**A replace, not a merge, and `.strict()`**: `self_registration`, `allowed_domains` and `allowed_origins` all arrive or the write is refused, so a client built against an older shape cannot silently clear a setting it does not know about. `oidc_callback_url` and `updated_at` are the server's, refused in this body as in every slice's \u2014 see `GET`'s notes for why. \n\n`400 validation_error` is where the two field rules land: an entry in `allowed_domains` must be lowercase, since a capitalised one can never match a lowercased address, and an entry in `allowed_origins` must be a bare scheme-host-port with no path, since a browser sends nothing longer in its `Origin` header. Each refuses at configuration time rather than failing silently later. \n\nThe merge is server-side against the stored row, so this write never disturbs the urls or mcp slice."
|
|
5872
|
+
},
|
|
5873
|
+
{
|
|
5874
|
+
method: "PUT",
|
|
5875
|
+
path: "/api/apps/:id/auth-config/urls",
|
|
5747
5876
|
section: "apps",
|
|
5748
|
-
summary: "Replaces the
|
|
5877
|
+
summary: "Replaces the three pages Fleetless's mails point at.",
|
|
5749
5878
|
audience: "developer",
|
|
5750
5879
|
auth: "developer",
|
|
5751
5880
|
rateLimited: false,
|
|
@@ -5753,11 +5882,29 @@ var ROUTES = [
|
|
|
5753
5882
|
status: 200,
|
|
5754
5883
|
params: [{ name: "id", description: "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`." }],
|
|
5755
5884
|
query: null,
|
|
5756
|
-
request:
|
|
5885
|
+
request: putAppAuthUrlsRequest,
|
|
5757
5886
|
response: appAuthConfig,
|
|
5758
5887
|
errors: [...DEVELOPER_GUARD, "invalid_uuid", "validation_error", "not_found"],
|
|
5759
5888
|
transport: "http",
|
|
5760
|
-
notes: "**A replace, not a merge, and `.strict()`**:
|
|
5889
|
+
notes: "**A replace, not a merge, and `.strict()`**: `invite_url`, `verify_url` and `reset_url` all arrive or the write is refused, so a client built against an older shape cannot silently clear a setting it does not know about. `oidc_callback_url` and `updated_at` are the server's, refused in this body as in every slice's \u2014 see `GET`'s notes for why. \n\n`400 validation_error` is where the field rule lands: a URL template must be https (or `http` on `localhost`) and carry its placeholder exactly once \u2014 a second occurrence leaves one literal in a mailed link, refused here rather than failing silently once the mail is sent. \n\nThe merge is server-side against the stored row, so this write never disturbs the registration or mcp slice."
|
|
5890
|
+
},
|
|
5891
|
+
{
|
|
5892
|
+
method: "PUT",
|
|
5893
|
+
path: "/api/apps/:id/auth-config/mcp",
|
|
5894
|
+
section: "apps",
|
|
5895
|
+
summary: "Replaces the MCP switch and its login URL together.",
|
|
5896
|
+
audience: "developer",
|
|
5897
|
+
auth: "developer",
|
|
5898
|
+
rateLimited: false,
|
|
5899
|
+
ownerTier: false,
|
|
5900
|
+
status: 200,
|
|
5901
|
+
params: [{ name: "id", description: "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`." }],
|
|
5902
|
+
query: null,
|
|
5903
|
+
request: putAppAuthMcpRequest,
|
|
5904
|
+
response: appAuthConfig,
|
|
5905
|
+
errors: [...DEVELOPER_GUARD, "invalid_uuid", "validation_error", "not_found"],
|
|
5906
|
+
transport: "http",
|
|
5907
|
+
notes: "**A replace, not a merge, and `.strict()`**: `mcp_enabled` and `mcp_login_url` both arrive or the write is refused, so a client built against an older shape cannot silently clear a setting it does not know about. `oidc_callback_url` and `updated_at` are the server's, refused in this body as in every slice's \u2014 see `GET`'s notes for why. \n\n`mcp_login_url` answers to the same rule as the `urls` slice's three templates \u2014 https (or `http` on `localhost`), its placeholder exactly once \u2014 refused as `400 validation_error` rather than left to fail mid-OAuth, in a client's browser where no console screen is watching. \n\nThe merge is server-side against the stored row, so this write never disturbs the registration or urls slice."
|
|
5761
5908
|
},
|
|
5762
5909
|
{
|
|
5763
5910
|
method: "GET",
|
|
@@ -7550,7 +7697,7 @@ var ROUTES = [
|
|
|
7550
7697
|
"internal_error"
|
|
7551
7698
|
],
|
|
7552
7699
|
transport: "http",
|
|
7553
|
-
notes: "**One route for both kinds**, because a path segment naming the kind would demand a fact a role grant does not carry. An action answers `202` with an `invokeResponse` the moment the job exists; a service answers `200` with a `serviceCallResponse` once the result is in \u2014 two shapes, carried by one union (`invokeOrServiceResponse`) and told apart by whether `kind` or a bare `result` arrives. Parameters are checked **before** anything about the world (offline, busy): the same request must get the same verdict whether or not the robot happens to be reachable, or a developer testing against an offline robot never learns their parameters were wrong. A service the robot reports as failed answers `502` carrying **the job's own error code**, which is an open set and not one of the codes above."
|
|
7700
|
+
notes: "**One route for both kinds**, because a path segment naming the kind would demand a fact a role grant does not carry. An action answers `202` with an `invokeResponse` the moment the job exists; a service answers `200` with a `serviceCallResponse` once the result is in \u2014 two shapes, carried by one union (`invokeOrServiceResponse`) and told apart by whether `kind` or a bare `result` arrives. Parameters are checked **before** anything about the world (offline, busy): the same request must get the same verdict whether or not the robot happens to be reachable, or a developer testing against an offline robot never learns their parameters were wrong. A slug is `409 busy` while it holds a `running` job, an `unknown` one the robot has not accounted for yet, or an `external` goal someone else started; the refusal's `details.running` names that job, `state` and `origin` included. A service the robot reports as failed answers `502` carrying **the job's own error code**, which is an open set and not one of the codes above."
|
|
7554
7701
|
},
|
|
7555
7702
|
{
|
|
7556
7703
|
method: "GET",
|
|
@@ -7591,9 +7738,21 @@ var ROUTES = [
|
|
|
7591
7738
|
request: cancelRequest,
|
|
7592
7739
|
requestOptional: true,
|
|
7593
7740
|
response: jobResponse,
|
|
7594
|
-
errors: [
|
|
7741
|
+
errors: [
|
|
7742
|
+
...CLIENT_GUARD,
|
|
7743
|
+
"invalid_uuid",
|
|
7744
|
+
"not_found",
|
|
7745
|
+
"validation_error",
|
|
7746
|
+
"not_cancellable",
|
|
7747
|
+
"robot_offline",
|
|
7748
|
+
"cancel_rejected",
|
|
7749
|
+
"bridge_timeout",
|
|
7750
|
+
"unknown_slug",
|
|
7751
|
+
"action_server_lost",
|
|
7752
|
+
"internal_error"
|
|
7753
|
+
],
|
|
7595
7754
|
transport: "http",
|
|
7596
|
-
notes:
|
|
7755
|
+
notes: "The body is optional: a bodyless `POST` was every caller's shape before `job_id` existed, and absent or `job_id: null` both mean \"cancel whatever is running\". A named `job_id` that is **not** what is running cancels nothing and answers `404` \u2014 the caller named an id and thereby ruled the other one out. An `external` job is cancelled the same way, through its goal id. Cancelling an `unknown` job also cancels every external goal on its action, since one of them may be that job. A service is `422 not_cancellable`: a service call has no goal to cancel. Nothing running is a `200` with `job: null`. The answer waits for the bridge's `cancel_result`: a `200` means the action server accepted the cancel request, not that the goal has ended \u2014 the job's end arrives as its own update. Any goal answered `ERROR_REJECTED` makes it `409 cancel_rejected`, with every goal and its `return_code` in `details.goals`; no answer within `JOB_HEARTBEAT_TIMEOUT_MS` is `504 bridge_timeout`; a cancel the bridge could not send at all is `502` carrying the bridge's own code (`unknown_slug`, `action_server_lost`, `internal_error`)."
|
|
7597
7756
|
},
|
|
7598
7757
|
{
|
|
7599
7758
|
method: "POST",
|
|
@@ -9199,9 +9358,11 @@ function deriveRealtimeUrl(apiUrl) {
|
|
|
9199
9358
|
}
|
|
9200
9359
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9201
9360
|
0 && (module.exports = {
|
|
9361
|
+
CANCEL_RETURN_CODES,
|
|
9202
9362
|
FleetlessError,
|
|
9203
9363
|
InMemoryTokenStore,
|
|
9204
9364
|
SDK_ERROR_CODES,
|
|
9365
|
+
cancelRejectedDetails,
|
|
9205
9366
|
createClient,
|
|
9206
9367
|
parameterInvalidDetails
|
|
9207
9368
|
});
|