@camstack/system 1.2.275 → 1.2.276
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/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/camera-grid/grid-last-frame-store.d.ts +39 -0
- package/dist/builtins/camera-grid/index.js +67 -12
- package/dist/builtins/camera-grid/index.mjs +67 -12
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-aggregation.d.ts +0 -6
- package/dist/builtins/device-manager/device-bindings-store.d.ts +12 -2
- package/dist/builtins/device-manager/device-manager.addon.d.ts +4 -0
- package/dist/builtins/device-manager/device-manager.addon.js +177 -58
- package/dist/builtins/device-manager/device-manager.addon.mjs +174 -59
- package/dist/builtins/device-manager/device-meta-types.d.ts +36 -3
- package/dist/builtins/device-manager/device-source-activation.d.ts +70 -0
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-DWSJVcZe.mjs → dist-AHdiIdJH.mjs} +331 -12
- package/dist/{dist-CYXhwfDf.js → dist-D_OlSf31.js} +336 -11
- package/dist/index.d.ts +7 -0
- package/dist/index.js +103 -37
- package/dist/index.mjs +101 -39
- package/dist/kernel/capability-registry.d.ts +59 -9
- package/dist/kernel/index.d.ts +1 -0
- package/dist/{retired-settings-keys-BHGnCLW0.mjs → retired-settings-keys-Cp3oG_aH.mjs} +1 -1
- package/dist/{retired-settings-keys-DEFtUH8o.js → retired-settings-keys-LwFyTKun.js} +1 -1
- package/package.json +2 -2
|
@@ -691,7 +691,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
691
691
|
return EventCategory;
|
|
692
692
|
}({});
|
|
693
693
|
//#endregion
|
|
694
|
-
//#region ../types/dist/sleep-
|
|
694
|
+
//#region ../types/dist/sleep-CopaBJss.mjs
|
|
695
695
|
/**
|
|
696
696
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
697
697
|
* window to float samples (D455).
|
|
@@ -892,6 +892,12 @@ var WELL_KNOWN_TAB_MAP = Object.fromEntries([
|
|
|
892
892
|
icon: "circle-dot",
|
|
893
893
|
order: 40
|
|
894
894
|
},
|
|
895
|
+
{
|
|
896
|
+
id: "clips",
|
|
897
|
+
label: "Clips",
|
|
898
|
+
icon: "clapperboard",
|
|
899
|
+
order: 41
|
|
900
|
+
},
|
|
895
901
|
{
|
|
896
902
|
id: "engine",
|
|
897
903
|
label: "Inference Engine",
|
|
@@ -2724,6 +2730,7 @@ function toNodeId(idOrRunnerId) {
|
|
|
2724
2730
|
function resolveCapMount(def) {
|
|
2725
2731
|
if (def.mount) return def.mount;
|
|
2726
2732
|
if (def.deviceNative === true) return { kind: "device-native" };
|
|
2733
|
+
if (def.scope === "device" && def.kind === "wrapper") return { kind: "device-scoped" };
|
|
2727
2734
|
if (def.mode === "collection") return { kind: "collection" };
|
|
2728
2735
|
return { kind: "singleton" };
|
|
2729
2736
|
}
|
|
@@ -10380,6 +10387,33 @@ function objectInputDeclaresAddonId(schema) {
|
|
|
10380
10387
|
const shape = direct !== void 0 && direct !== null ? direct : resolveDefShape(schema._def?.shape);
|
|
10381
10388
|
return shape !== void 0 && shape !== null && typeof shape === "object" && Object.prototype.hasOwnProperty.call(shape, "addonId");
|
|
10382
10389
|
}
|
|
10390
|
+
/**
|
|
10391
|
+
* True when an OBJECT input schema declares a top-level, REQUIRED, numeric
|
|
10392
|
+
* `deviceId` — i.e. the method names exactly one device on every call.
|
|
10393
|
+
*
|
|
10394
|
+
* This is the question the per-device dispatcher asks at runtime
|
|
10395
|
+
* (`requireDeviceScoped`: `typeof input.deviceId !== 'number'` → BAD_REQUEST),
|
|
10396
|
+
* asked once at build time instead. A `device-scoped` cap's method that cannot
|
|
10397
|
+
* answer it has no device to resolve for and therefore resolves through the
|
|
10398
|
+
* cap's SYSTEM provider (`cap-router-builder.ts`) — the same destination
|
|
10399
|
+
* `systemOnly` names explicitly. Without this, flipping the mount would 400
|
|
10400
|
+
* every batch (`deviceIds`), fleet-wide (`z.void()`) and job-keyed method on
|
|
10401
|
+
* the eight device-scoped wrapper caps.
|
|
10402
|
+
*
|
|
10403
|
+
* Structural, never a name heuristic over source text: the field must resolve
|
|
10404
|
+
* to `z.number()` and must NOT be wrapped in `optional` / `nullable` /
|
|
10405
|
+
* `default` — an absent value is exactly the input the dispatcher rejects.
|
|
10406
|
+
*/
|
|
10407
|
+
function objectInputDeclaresRequiredDeviceId(schema) {
|
|
10408
|
+
if (schema === null || typeof schema !== "object" && typeof schema !== "function") return false;
|
|
10409
|
+
const direct = schema.shape;
|
|
10410
|
+
const shape = direct !== void 0 && direct !== null ? direct : resolveDefShape(schema._def?.shape);
|
|
10411
|
+
if (shape === void 0 || shape === null || typeof shape !== "object") return false;
|
|
10412
|
+
const field = shape["deviceId"];
|
|
10413
|
+
if (field === void 0 || field === null) return false;
|
|
10414
|
+
const def = field._def;
|
|
10415
|
+
return field.constructor?.name === "ZodNumber" || def?.type === "number" || def?.typeName === "ZodNumber";
|
|
10416
|
+
}
|
|
10383
10417
|
/** `_def.shape` may be a thunk (Zod defers object-shape evaluation) or a plain record. */
|
|
10384
10418
|
function resolveDefShape(defShape) {
|
|
10385
10419
|
return typeof defShape === "function" ? defShape() : defShape;
|
|
@@ -13210,14 +13244,30 @@ var deviceManagerCapability = {
|
|
|
13210
13244
|
*/
|
|
13211
13245
|
getAllBindings: method(z.object({}), z.array(DeviceBindingsForDeviceSchema)),
|
|
13212
13246
|
/**
|
|
13213
|
-
* Activate (or deactivate) a wrapper addon
|
|
13214
|
-
*
|
|
13215
|
-
*
|
|
13247
|
+
* Activate (or deactivate) a wrapper addon — or ONE of its sources — for a
|
|
13248
|
+
* (device, cap) pair.
|
|
13249
|
+
*
|
|
13250
|
+
* Persists the binding via ctx.settings; `active: false` on a SINGLETON cap
|
|
13251
|
+
* clears the wrapper (falling back to native if one is registered). On a
|
|
13252
|
+
* COLLECTION cap it adds to the per-device DENY set instead, and the
|
|
13253
|
+
* wrapper binding is left exactly as it was — a cap with several sources
|
|
13254
|
+
* has no "which one" for `getBindings` to answer (D556).
|
|
13255
|
+
*
|
|
13256
|
+
* `sourceId` is what makes the switch match its label. One addon can serve
|
|
13257
|
+
* several of a device's sources (`addon-provider-reolink` answers a hub
|
|
13258
|
+
* child with `native:reolink:onboard` AND `native:reolink:hub`), so a
|
|
13259
|
+
* toggle keyed by addon would turn off both while saying it turned off one
|
|
13260
|
+
* — the D62 defect with the polarity reversed (D557). Naming the source
|
|
13261
|
+
* denies exactly that source. OMITTING it keeps the cap-wide meaning
|
|
13262
|
+
* D556 shipped: every source this addon serves for this device, which is
|
|
13263
|
+
* also how a deny entry persisted before the re-key is still read.
|
|
13216
13264
|
*/
|
|
13217
13265
|
setWrapperActive: method(z.object({
|
|
13218
13266
|
deviceId: z.number(),
|
|
13219
13267
|
capName: z.string(),
|
|
13220
13268
|
wrapperAddonId: z.string(),
|
|
13269
|
+
/** The `ClipSource.source` id to toggle. Absent = all of the addon's. */
|
|
13270
|
+
sourceId: z.string().optional(),
|
|
13221
13271
|
active: z.boolean()
|
|
13222
13272
|
}), z.void(), {
|
|
13223
13273
|
kind: "mutation",
|
|
@@ -25975,41 +26025,299 @@ var ClipSchema = z.object({
|
|
|
25975
26025
|
holes: z.array(z.object({
|
|
25976
26026
|
startMs: z.number(),
|
|
25977
26027
|
endMs: z.number()
|
|
25978
|
-
})).optional()
|
|
26028
|
+
})).optional(),
|
|
26029
|
+
/**
|
|
26030
|
+
* A URL that MAY produce this clip's still, asked only for rows actually on
|
|
26031
|
+
* screen. The opposite of {@link ClipSchema.thumbnail}: that one is VOUCHED
|
|
26032
|
+
* (a JPEG is already on disk), this one is an offer. The route answers 200
|
|
26033
|
+
* with the image, or 204 with `x-camstack-reason` when it could not mint one
|
|
26034
|
+
* — a surface latches that refusal to the instant rather than retrying.
|
|
26035
|
+
*
|
|
26036
|
+
* Never both: a clip with a vouched `thumbnail` needs no mint.
|
|
26037
|
+
*/
|
|
26038
|
+
thumbnailMint: z.string().optional(),
|
|
26039
|
+
/**
|
|
26040
|
+
* Why no still will be produced for this clip RIGHT NOW — set when the
|
|
26041
|
+
* provider already knows, so the surface draws the glyph and the reason
|
|
26042
|
+
* instead of firing a mint that cannot succeed.
|
|
26043
|
+
*
|
|
26044
|
+
* `sleeping` — a standalone battery camera; a read would be a wake (D549 4).
|
|
26045
|
+
* `camera-refused` — the camera answered the CoverPreview with a refusal.
|
|
26046
|
+
* `no-keyframe` — the window holds no decodable I-frame (an event that sits
|
|
26047
|
+
* inside no file is the measured case).
|
|
26048
|
+
* `unsupported` — this source cannot mint stills at all.
|
|
26049
|
+
*/
|
|
26050
|
+
thumbnailUnavailable: z.object({ reason: z.enum([
|
|
26051
|
+
"sleeping",
|
|
26052
|
+
"camera-refused",
|
|
26053
|
+
"no-keyframe",
|
|
26054
|
+
"unsupported"
|
|
26055
|
+
]) }).optional(),
|
|
26056
|
+
/**
|
|
26057
|
+
* When the catalog this row came from was last CONFIRMED against the device.
|
|
26058
|
+
* Absent means "this row was read live". A persisted catalog served while a
|
|
26059
|
+
* camera sleeps carries the age it really has — a cached list is never drawn
|
|
26060
|
+
* as current (D549 13).
|
|
26061
|
+
*/
|
|
26062
|
+
catalogAsOf: z.number().optional(),
|
|
26063
|
+
/**
|
|
26064
|
+
* The camera's OWN type strings for this clip, all of them, unmapped
|
|
26065
|
+
* (`md`, `people`, `dog_cat`, `sched`, …). Kept beside {@link labels}
|
|
26066
|
+
* because a firmware inventing a type must not vanish: the mapping into our
|
|
26067
|
+
* filter vocabulary is lossy on purpose and this is the lossless copy
|
|
26068
|
+
* (D549 20).
|
|
26069
|
+
*/
|
|
26070
|
+
nativeTypes: z.array(z.string()).optional(),
|
|
26071
|
+
/**
|
|
26072
|
+
* What the subject DID — `crossline`, `intrude`, `loitering`. A behaviour
|
|
26073
|
+
* travels BESIDE a class, never instead of one, and the class filter ignores
|
|
26074
|
+
* it: "a person crossed a line" is still a person (D549 20).
|
|
26075
|
+
*/
|
|
26076
|
+
behaviours: z.array(z.string()).optional(),
|
|
26077
|
+
/**
|
|
26078
|
+
* The same recording as two files — the sub twin (what the row and its
|
|
26079
|
+
* thumbnail are) and its main twin, matched at listing time so a quality
|
|
26080
|
+
* change never re-searches the camera (D549 15). `getClipPlayback`'s
|
|
26081
|
+
* `profile` picks between them: `low | mid` → sub, `high` → main.
|
|
26082
|
+
*/
|
|
26083
|
+
streams: z.object({
|
|
26084
|
+
sub: z.object({
|
|
26085
|
+
id: z.string(),
|
|
26086
|
+
bytes: z.number().optional()
|
|
26087
|
+
}).optional(),
|
|
26088
|
+
main: z.object({
|
|
26089
|
+
id: z.string(),
|
|
26090
|
+
bytes: z.number().optional()
|
|
26091
|
+
}).optional()
|
|
26092
|
+
}).optional(),
|
|
26093
|
+
/** The camera says it holds a sub-stream copy of this recording. */
|
|
26094
|
+
supportSub: z.boolean().optional(),
|
|
26095
|
+
/**
|
|
26096
|
+
* Whether this row has bytes behind it. ABSENT means yes — every clip that
|
|
26097
|
+
* IS a file is playable, and only a source that lists EVENTS can produce a
|
|
26098
|
+
* row with nothing to play (the measured case: 1 of 29 hub events on 3628
|
|
26099
|
+
* fell inside no file). Such a row is shown, never dropped and never offered
|
|
26100
|
+
* as playable-then-failing (D549 19).
|
|
26101
|
+
*/
|
|
26102
|
+
playable: z.boolean().optional(),
|
|
26103
|
+
/** Why {@link playable} is false, verbatim (`no-file-for-window`). */
|
|
26104
|
+
unplayableReason: z.string().optional()
|
|
25979
26105
|
});
|
|
25980
26106
|
var ClipPlaybackSchema = z.object({
|
|
25981
|
-
/**
|
|
26107
|
+
/**
|
|
26108
|
+
* A media URL through the hub data-plane. {@link ClipPlaybackSchema.format}
|
|
26109
|
+
* says what kind — an HLS master playlist for a recording-derived clip, a
|
|
26110
|
+
* progressive MP4 for a native file the vendor addon muxed and serves with
|
|
26111
|
+
* `Range`. The URL is NOT a credential: both planes are registered
|
|
26112
|
+
* `access: 'authenticated'` and the hub's `/addon/<id>/<prefix>` proxy takes
|
|
26113
|
+
* the session cookie, so nothing is appended to it (D549 22).
|
|
26114
|
+
*/
|
|
25982
26115
|
playbackUrl: z.string(),
|
|
26116
|
+
/**
|
|
26117
|
+
* How to play {@link playbackUrl}. Absent means `hls` — the shape every
|
|
26118
|
+
* existing consumer already assumes. A player that branches on this is the
|
|
26119
|
+
* one change a native clip needs; a player that ignores it will hand an MP4
|
|
26120
|
+
* to hls.js and fail parsing it as a manifest.
|
|
26121
|
+
*/
|
|
26122
|
+
format: z.enum(["hls", "mp4"]).optional(),
|
|
26123
|
+
/**
|
|
26124
|
+
* Which twin was actually served. A clip that holds only one stream answers
|
|
26125
|
+
* with the one it has, and the surface SAYS so — a missing main twin is
|
|
26126
|
+
* never served silently as if it were the asked-for quality (D549 15).
|
|
26127
|
+
*/
|
|
26128
|
+
served: CamProfileSchema.optional(),
|
|
25983
26129
|
/** Optional LAN/remote alternates for the same clip. */
|
|
25984
26130
|
playbackEndpoints: z.array(z.string()).optional(),
|
|
25985
26131
|
token: z.string().optional()
|
|
25986
26132
|
});
|
|
26133
|
+
/**
|
|
26134
|
+
* Why a source cannot answer right now — per SOURCE, never fleet-wide.
|
|
26135
|
+
*
|
|
26136
|
+
* `ok` is the only state whose clip list may be read as complete. The other
|
|
26137
|
+
* three exist because an empty list from a sleeping camera reads as "this
|
|
26138
|
+
* camera has no recordings", which is the defect this whole line of work is
|
|
26139
|
+
* about: a battery camera nobody woke (`sleeping`), a camera that could not be
|
|
26140
|
+
* reached at all (`unreachable`, also what a provider that THREW reports), a
|
|
26141
|
+
* camera whose SD card is not mounted (`no-storage`, measured on 640 —
|
|
26142
|
+
* `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
|
|
26143
|
+
* camera whose OWN index disagrees with its OWN calendar (`index-empty`,
|
|
26144
|
+
* measured on 618: the calendar marks 3–20 September, days 6–20 list zero
|
|
26145
|
+
* files on both streams and both filters, with 177 GB free). That last one is
|
|
26146
|
+
* a defect ON THE CAMERA, and the only honest thing a provider can do is say
|
|
26147
|
+
* which days it asked for and got nothing — "no clips" would be a lie about a
|
|
26148
|
+
* card that is full of them.
|
|
26149
|
+
*/
|
|
26150
|
+
var ClipSourceAvailabilitySchema = z.object({
|
|
26151
|
+
state: z.enum([
|
|
26152
|
+
"ok",
|
|
26153
|
+
"sleeping",
|
|
26154
|
+
"unreachable",
|
|
26155
|
+
"no-storage",
|
|
26156
|
+
"index-empty"
|
|
26157
|
+
]),
|
|
26158
|
+
/** Free text, shown verbatim. Names the camera's own refusal when there is one. */
|
|
26159
|
+
reason: z.string().optional(),
|
|
26160
|
+
/** When this source's catalog was last CONFIRMED. A cached list is never
|
|
26161
|
+
* drawn as current: the surface shows the age whenever it is older than the
|
|
26162
|
+
* refresh interval. */
|
|
26163
|
+
catalogAsOf: z.number().optional()
|
|
26164
|
+
});
|
|
26165
|
+
/**
|
|
26166
|
+
* One SOURCE of clips for a camera — a row of the picker, and the namespace
|
|
26167
|
+
* every clip id from it is prefixed with (`analytics`,
|
|
26168
|
+
* `native:reolink:onboard`, `hksv`, …).
|
|
26169
|
+
*
|
|
26170
|
+
* A provider lists the sources IT serves for that device, and answers for each
|
|
26171
|
+
* of them whether it can answer at all. A provider with nothing to offer on a
|
|
26172
|
+
* camera returns `[]` — it is not that camera's business.
|
|
26173
|
+
*/
|
|
26174
|
+
var ClipSourceSchema = z.object({
|
|
26175
|
+
/** The value this source stamps on {@link ClipSchema.source}, and the prefix
|
|
26176
|
+
* of every clip id it mints. `getClipPlayback` routes on it. */
|
|
26177
|
+
source: z.string(),
|
|
26178
|
+
/** Operator-facing name of the source ("CamStack recordings", "SD card"). */
|
|
26179
|
+
label: z.string(),
|
|
26180
|
+
/**
|
|
26181
|
+
* The addon that SERVES this row.
|
|
26182
|
+
*
|
|
26183
|
+
* A surface cannot otherwise resolve a source to who answers it, and the
|
|
26184
|
+
* alternative — a `native:reolink:* → provider-reolink` table inside the
|
|
26185
|
+
* widget — is a second authority on provider identity living in the one
|
|
26186
|
+
* package with no business knowing it, wrong the day a third source appears
|
|
26187
|
+
* (D557). One addon may serve SEVERAL sources: `addon-provider-reolink`
|
|
26188
|
+
* answers a hub child with both `native:reolink:onboard` and
|
|
26189
|
+
* `native:reolink:hub`, which is why the per-device switch is keyed by
|
|
26190
|
+
* SOURCE and not by this (D555).
|
|
26191
|
+
*
|
|
26192
|
+
* Optional for version skew only. The collection dispatcher stamps it from
|
|
26193
|
+
* the registry, so a row that travelled through the fan-out carries the
|
|
26194
|
+
* authoritative id whatever the provider filled in.
|
|
26195
|
+
*/
|
|
26196
|
+
addonId: z.string().optional(),
|
|
26197
|
+
/**
|
|
26198
|
+
* Which API this source resolved to FOR THIS CAMERA, when it has a choice.
|
|
26199
|
+
*
|
|
26200
|
+
* A source may cover one store through more than one surface — the Reolink
|
|
26201
|
+
* provider reads a hub child through the parent's event log and a standalone
|
|
26202
|
+
* through its own file list, because that is what each camera answers. The
|
|
26203
|
+
* CHOICE is the provider's, made from what the camera is, and is never a row
|
|
26204
|
+
* the operator has to understand; but it is REPORTED, because a source that
|
|
26205
|
+
* silently reads a different API on two cameras and then behaves differently
|
|
26206
|
+
* is the thing nobody can debug later. Absent when the source has only one
|
|
26207
|
+
* way to read its store.
|
|
26208
|
+
*/
|
|
26209
|
+
via: z.string().optional(),
|
|
26210
|
+
availability: ClipSourceAvailabilitySchema,
|
|
26211
|
+
/**
|
|
26212
|
+
* The operator switched this source OFF for this camera.
|
|
26213
|
+
*
|
|
26214
|
+
* Deliberately NOT a member of {@link ClipSourceAvailabilitySchema}'s
|
|
26215
|
+
* vocabulary. That enum models what the source CAN do — a sleeping camera, an
|
|
26216
|
+
* unmounted card, an index that disagrees with its own calendar — and a
|
|
26217
|
+
* switched-off source could answer perfectly well; the operator decided it
|
|
26218
|
+
* should not. Folding the choice in is how `disabled` and `broken` stop being
|
|
26219
|
+
* distinguishable, which is the D62 rule this repo has already paid for twice:
|
|
26220
|
+
* an off switch is REPORTED off (`CameraStatus.switchedOff`, the same word),
|
|
26221
|
+
* and disabled must never look like broken. It is also what lets every
|
|
26222
|
+
* exhaustive consumer of the availability enum keep compiling.
|
|
26223
|
+
*
|
|
26224
|
+
* A switched-off source contributes NO clips (`listClips` never calls it) and
|
|
26225
|
+
* its row carries no `catalogAsOf`: nothing confirms a catalog it is not
|
|
26226
|
+
* allowed to serve, and a frozen age that can only grow draws a stalling
|
|
26227
|
+
* source rather than an off switch.
|
|
26228
|
+
*
|
|
26229
|
+
* The row survives BECAUSE it is the control the operator switches the source
|
|
26230
|
+
* back on from — D554 decision 4's rule ("a source that cannot answer
|
|
26231
|
+
* produces a ROW, not an absence") applied to the one case D556 carved out of
|
|
26232
|
+
* it, and D557's own kept property ("a source is never hidden, only its
|
|
26233
|
+
* rows"). Absent means on.
|
|
26234
|
+
*
|
|
26235
|
+
* A provider never sets this — like {@link ClipSourceSchema.addonId} it is
|
|
26236
|
+
* stamped by the collection dispatcher, which holds the registry's projection
|
|
26237
|
+
* of the persisted authority (D556) and is the only place that knows it.
|
|
26238
|
+
*/
|
|
26239
|
+
switchedOff: z.boolean().optional()
|
|
26240
|
+
});
|
|
25987
26241
|
var videoclipsCapability = {
|
|
25988
26242
|
name: "videoclips",
|
|
25989
26243
|
scope: "device",
|
|
25990
|
-
mode: "
|
|
26244
|
+
mode: "collection",
|
|
25991
26245
|
kind: "wrapper",
|
|
25992
26246
|
defaultActive: true,
|
|
25993
26247
|
/** A clip is a window over a camera's footage — the cap is meaningless on a
|
|
25994
26248
|
* sensor, a button or an event emitter, and the `defaultActive` auto-bind
|
|
25995
26249
|
* reads this to decide which devices it may claim. */
|
|
25996
26250
|
deviceTypes: [DeviceType.Camera],
|
|
26251
|
+
/**
|
|
26252
|
+
* The Clips section of a camera's device details is FRAMEWORK-DERIVED (D14):
|
|
26253
|
+
* the aggregator turns this declaration into the `type:'widget'` section and
|
|
26254
|
+
* `DeviceDetail.tsx` is never edited. `videoclips` is the first WRAPPER cap
|
|
26255
|
+
* to declare one — every previous `host/` widget cap is `deviceNative` — so
|
|
26256
|
+
* `device-config-widget-wrapped-binding.spec.ts` pins that a `kind:'wrapped'`
|
|
26257
|
+
* binding entry derives the same section a native one does.
|
|
26258
|
+
*
|
|
26259
|
+
* `topTab` because the browser owns the whole pane (a day's clips, a source
|
|
26260
|
+
* list and a player), exactly as `ptz` does; the widget itself is
|
|
26261
|
+
* `host/clips-browser` in ui-library's `HOST_WIDGETS`.
|
|
26262
|
+
*/
|
|
26263
|
+
deviceConfig: { ui: {
|
|
26264
|
+
kind: "widget",
|
|
26265
|
+
widgetId: "host/clips-browser",
|
|
26266
|
+
tab: "clips",
|
|
26267
|
+
topTab: true,
|
|
26268
|
+
label: "Clips",
|
|
26269
|
+
order: 0
|
|
26270
|
+
} },
|
|
25997
26271
|
methods: {
|
|
25998
26272
|
listClips: method(z.object({
|
|
25999
26273
|
deviceId: z.number(),
|
|
26000
26274
|
since: z.number(),
|
|
26001
26275
|
until: z.number(),
|
|
26002
|
-
limit: z.number().int().positive().optional()
|
|
26276
|
+
limit: z.number().int().positive().optional(),
|
|
26277
|
+
/**
|
|
26278
|
+
* View filter over {@link ClipSourceSchema.source} values — the
|
|
26279
|
+
* picker's selection, forwarded so a provider need not list what
|
|
26280
|
+
* nobody is looking at. ABSENT means every source this camera has,
|
|
26281
|
+
* which is the honest default for a surface whose whole point is that
|
|
26282
|
+
* nothing is hidden (D554 3). A provider with one source ignores it.
|
|
26283
|
+
*/
|
|
26284
|
+
sources: z.array(z.string()).optional()
|
|
26003
26285
|
}), z.array(ClipSchema).readonly(), {
|
|
26004
26286
|
kind: "query",
|
|
26005
|
-
auth: "
|
|
26287
|
+
auth: "protected"
|
|
26288
|
+
}),
|
|
26289
|
+
/**
|
|
26290
|
+
* The sources this camera has, WITH the reason any of them cannot answer.
|
|
26291
|
+
*
|
|
26292
|
+
* Asked separately from `listClips` because an empty clip list is
|
|
26293
|
+
* ambiguous and this is the only place the ambiguity is resolved: every
|
|
26294
|
+
* bound provider contributes its own rows, and a provider that could not
|
|
26295
|
+
* be reached at all still produces one row saying so. A surface that draws
|
|
26296
|
+
* "no clips" without reading this is drawing a guess.
|
|
26297
|
+
*/
|
|
26298
|
+
listSources: method(z.object({ deviceId: z.number() }), z.array(ClipSourceSchema).readonly(), {
|
|
26299
|
+
kind: "query",
|
|
26300
|
+
auth: "protected"
|
|
26006
26301
|
}),
|
|
26007
26302
|
getClipPlayback: method(z.object({
|
|
26008
26303
|
deviceId: z.number(),
|
|
26009
|
-
clipId: z.string()
|
|
26304
|
+
clipId: z.string(),
|
|
26305
|
+
/**
|
|
26306
|
+
* Which twin to serve, on the ONE quality scale the system already has
|
|
26307
|
+
* (`CamProfileSchema`). `low | mid` → the sub file, `high` → the main
|
|
26308
|
+
* twin; both ids are already on the row so this never re-searches the
|
|
26309
|
+
* camera. Absent means the provider's own default (the sub file, which
|
|
26310
|
+
* every source is measured to hold).
|
|
26311
|
+
*
|
|
26312
|
+
* `auto` is deliberately NOT accepted here: a stored file has no
|
|
26313
|
+
* broker session, so the adaptive tier cannot be resolved for it. The
|
|
26314
|
+
* viewer resolves `auto` to a profile the same way live does, before
|
|
26315
|
+
* it calls (D549 15).
|
|
26316
|
+
*/
|
|
26317
|
+
profile: CamProfileSchema.optional()
|
|
26010
26318
|
}), ClipPlaybackSchema, {
|
|
26011
26319
|
kind: "query",
|
|
26012
|
-
auth: "
|
|
26320
|
+
auth: "protected"
|
|
26013
26321
|
})
|
|
26014
26322
|
}
|
|
26015
26323
|
};
|
|
@@ -45989,6 +46297,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
45989
46297
|
addonId: null,
|
|
45990
46298
|
access: "view"
|
|
45991
46299
|
},
|
|
46300
|
+
"videoclips.listSources": {
|
|
46301
|
+
capName: "videoclips",
|
|
46302
|
+
capScope: "device",
|
|
46303
|
+
addonId: null,
|
|
46304
|
+
access: "view"
|
|
46305
|
+
},
|
|
45992
46306
|
"viewerUi.getStaticDir": {
|
|
45993
46307
|
capName: "viewer-ui",
|
|
45994
46308
|
capScope: "system",
|
|
@@ -47997,6 +48311,11 @@ Object.freeze({
|
|
|
47997
48311
|
form: "single",
|
|
47998
48312
|
optional: false
|
|
47999
48313
|
}],
|
|
48314
|
+
"videoclips.listSources": [{
|
|
48315
|
+
name: "deviceId",
|
|
48316
|
+
form: "single",
|
|
48317
|
+
optional: false
|
|
48318
|
+
}],
|
|
48000
48319
|
"waterHeater.setAway": [{
|
|
48001
48320
|
name: "deviceId",
|
|
48002
48321
|
form: "single",
|
|
@@ -49119,4 +49438,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
49119
49438
|
return out;
|
|
49120
49439
|
}
|
|
49121
49440
|
//#endregion
|
|
49122
|
-
export { deviceStateCapability as $,
|
|
49441
|
+
export { deviceStateCapability as $, storageProviderCapability as $t, StorageLocationModeSchema as A, parseJsonUnknown as An, motionCapability as At, bareAddonId as B, resolveContainerPrimaryChild as Bt, RecordingStatusSchema as C, emitReadiness as Cn, logDestinationCapability as Ct, STREAM_PROFILE_META as D, isEvent as Dn, mayWriteToLocation as Dt, STORAGE_ACCESS_FALLBACK as E, isDeviceConfigCap as En, mayReadLocation as Et, addonSettingsCapability as F, EventCategory as Fn, platformProbeCapability as Ft, coreBlockAddonId as G, scopesAllowDeviceCap as Gt, buildStreamParamsConfigSchema as H, resolveMethodAuth as Ht, addonWidgetsCapability as I, procedureAuthKey as It, dataStoreProviderCapability as J, siteZoneKey as Jt, coreBlockIdFromAddonId as K, scoreRuntimes as Kt, alertsCapability as L, ptzAutotrackCapability as Lt, StorageMigrationJobSchema as M, resolveCapMount as Mn, objectInputDeclaresAddonId as Mt, UserRecordSchema as N, scopeKey as Nn, objectInputDeclaresRequiredDeviceId as Nt, ScopedTokenSchema as O, nodePin as On, metricsProviderCapability as Ot, addonPagesCapability as P, sleep as Pn, parseStreamParamsFormPatch as Pt, deviceManagerCapability as Q, storageOccupancyCapability as Qt, authProviderCapability as R, reducePoints as Rt, RUNTIME_DEFAULTS as S, emitDownForOwnedCaps as Sn, locationIconKey as St, SOURCE_DEVICE_TYPES as T, hydrateSchema as Tn, looseSchema as Tt, cameraGridLayoutCapability as U, runtimeStatePolicyFor as Ut, batteryCapability as V, resolveLocationMode as Vt, collectSecretConfigKeys as W, scopesAllowAddon as Wt, decodeVectorBase64 as X, storageCapability as Xt, declarationOwnerNodeId as Y, snapshotCapability as Yt, deriveBatteryPresence as Z, storageMigrationCapability as Zt, LegacyStorageLocationDefaultSchema as _, WELL_KNOWN_TAB_MAP as _n, isVoidInput as _t, BatteryStatusSchema as a, withLocationMode as an, evaluateSensorEdge as at, MOTION_CLOSE_AFTER_MS as b, asString as bn, lifecycleJobSchema as bt, CORE_BLOCKS_ADDON_ID as c, BaseAddon as cn, filesystemBrowseCapability as ct, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as d, DEVICE_STATUS_METHOD as dn, isArrayOutputSchema as dt, streamCatalogCapability as en, deviceStatusCapability as et, DERIVED_CAMERA_SILENCED_CAP_NAMES as f, DeviceFeature as fn, isCollectionArrayMethod as ft, LOG_LEVEL_RANK as g, ReadinessTimeoutError as gn, isSourceCap as gt, FIRST_LEVEL_MACRO_CLASSES as h, ReadinessRegistry as hn, isSameAddonId as ht, BaseDevice as i, vectorStoreCapability as in, enumerateSchemaFields as it, StorageLocationTypeSchema as j, readinessKey as jn, normalizeUnit as jt, StorageCleanupJobSchema as k, parseJsonObject as kn, modeMayWrite as kt, CORE_BLOCK_ADDON_PREFIX as l, DATAPLANE_SECRET_HEADER as ln, foldSnapshotByFunction as lt, DeviceStatusSchema as m, DeviceType as mn, isObjectInput as mt, AlertSchema as n, userManagementCapability as nn, enumerateInferenceDevices as nt, CAMERA_SWITCH_ORDER as o, errMsg as on, evictionPolicyOfLocation as ot, DeclaredDevices as p, DeviceRole as pn, isLocationEnabled as pt, coreBlocksCapability as q, settingsStoreCapability as qt, ApiKeyRecordSchema as r, vectorDimFromBase64 as rn, enumerateItemArrayFields as rt, CAP_NAMES_WITH_STATUS as s, buildFfmpegArgs as sn, extractNestedAddonId as st, ALL_CAPABILITY_DEFINITIONS as t, streamQualityLabel as tn, doorbellCapability as tt, CoreBlockSchema as u, DEVICE_SETTINGS_CONTRIBUTION_METHODS as un, gbToBytes as ut, LocationIconIdSchema as v, asJsonObject as vn, kebabToCamel as vt, SOURCE_CAPS as w, expandCapMethods as wn, logLevelAtMost as wt, REDACTED_SECRET as x, createEvent as xn, localNetworkCapability as xt, METHOD_ACCESS_MAP as y, asNumber as yn, legacyModeOf as yt, backupCapability as z, resolveBucketMs as zt };
|