@camstack/addon-osd-manager 0.1.122 → 0.1.124
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/{MotionZonesSettings-De9jWRua.mjs → MotionZonesSettings-DOFOB5MX.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-DTroGBjn.mjs → PrivacyMaskSettings-9rCXAZlR.mjs} +4 -4
- package/dist/{SceneMonitorEditor-CmAP9oBX.mjs → SceneMonitorEditor-D2ATIIZD.mjs} +3 -3
- package/dist/_stub.js +12 -12
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-DHyei7uF.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-B2cBM7jE.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BK-eslgm.mjs +26 -0
- package/dist/addon-osd-manager.css +1 -1
- package/dist/{hostInit-Boz2o85e.mjs → hostInit-Du2Me1GR.mjs} +2 -2
- package/dist/index.js +403 -18
- package/dist/index.mjs +403 -18
- package/dist/{player-overlays-B4bQG7Zk.mjs → player-overlays-CMeXfcep.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-BQ-roliB.mjs → responsive-CC0j2h-d.mjs} +1 -1
- package/dist/{scene-monitor-copy-a2fD65-t.mjs → scene-monitor-copy-CjiHJ4pT.mjs} +1 -1
- package/dist/{square-BnphANwM.mjs → square-hvOcBhdH.mjs} +1 -1
- package/dist/{trash-2-UWP69ygY.mjs → trash-2-rb-x3jwf.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-CWN5igsE.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-D8j_yb3G.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C1Dujrj5.mjs +0 -26
package/dist/index.mjs
CHANGED
|
@@ -5359,7 +5359,7 @@ var ZodIssueCode = {
|
|
|
5359
5359
|
var ZodFirstPartyTypeKind;
|
|
5360
5360
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5361
5361
|
//#endregion
|
|
5362
|
-
//#region ../types/dist/sleep-
|
|
5362
|
+
//#region ../types/dist/sleep-CopaBJss.mjs
|
|
5363
5363
|
/**
|
|
5364
5364
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5365
5365
|
* window to float samples (D455).
|
|
@@ -5559,6 +5559,12 @@ Object.fromEntries([
|
|
|
5559
5559
|
icon: "circle-dot",
|
|
5560
5560
|
order: 40
|
|
5561
5561
|
},
|
|
5562
|
+
{
|
|
5563
|
+
id: "clips",
|
|
5564
|
+
label: "Clips",
|
|
5565
|
+
icon: "clapperboard",
|
|
5566
|
+
order: 41
|
|
5567
|
+
},
|
|
5562
5568
|
{
|
|
5563
5569
|
id: "engine",
|
|
5564
5570
|
label: "Inference Engine",
|
|
@@ -8303,11 +8309,31 @@ var RecordingBandTriggersSchema = RecordingTriggersSchema;
|
|
|
8303
8309
|
* band engine's `applies` rule). `start`/`end` are `HH:MM`; an `end <= start`
|
|
8304
8310
|
* span wraps past midnight (handled by the band engine).
|
|
8305
8311
|
*/
|
|
8312
|
+
/**
|
|
8313
|
+
* Whether a band's footage carries sound.
|
|
8314
|
+
*
|
|
8315
|
+
* The recorder has always attached with `audio: 'aac'`, so every band of every
|
|
8316
|
+
* camera recorded sound whether anyone wanted it or not. The broker already
|
|
8317
|
+
* serves the other answer — `audio: 'none'` takes the video-only `/muted`
|
|
8318
|
+
* restream — so this was a choice the product could always have offered.
|
|
8319
|
+
*
|
|
8320
|
+
* It belongs on the BAND rather than the camera because one camera can want
|
|
8321
|
+
* both: silent across the shop floor during opening hours, sound overnight.
|
|
8322
|
+
* And it applies to BOTH modes — an events band firing on motion has the same
|
|
8323
|
+
* question to answer as a continuous one.
|
|
8324
|
+
*/
|
|
8325
|
+
var RecordingBandAudioSchema = _enum(["on", "muted"]);
|
|
8306
8326
|
var RecordingBandSchema = object({
|
|
8307
8327
|
days: array(RecordingWeekdaySchema),
|
|
8308
8328
|
start: string().regex(HHMM),
|
|
8309
8329
|
end: string().regex(HHMM),
|
|
8310
8330
|
mode: RecordingBandModeSchema,
|
|
8331
|
+
/**
|
|
8332
|
+
* Sound, or silence. OPTIONAL and absent-means-`on`: every recording
|
|
8333
|
+
* written before this existed carried sound, and a band whose key is
|
|
8334
|
+
* missing must keep meaning what it meant. See {@link RecordingBandAudioSchema}.
|
|
8335
|
+
*/
|
|
8336
|
+
audio: RecordingBandAudioSchema.optional(),
|
|
8311
8337
|
triggers: RecordingBandTriggersSchema.optional(),
|
|
8312
8338
|
/**
|
|
8313
8339
|
* RETIRED (D381). A band no longer carries a pre-buffer of its own.
|
|
@@ -15916,14 +15942,30 @@ var deviceManagerCapability = {
|
|
|
15916
15942
|
*/
|
|
15917
15943
|
getAllBindings: method(object({}), array(DeviceBindingsForDeviceSchema)),
|
|
15918
15944
|
/**
|
|
15919
|
-
* Activate (or deactivate) a wrapper addon
|
|
15920
|
-
*
|
|
15921
|
-
*
|
|
15945
|
+
* Activate (or deactivate) a wrapper addon — or ONE of its sources — for a
|
|
15946
|
+
* (device, cap) pair.
|
|
15947
|
+
*
|
|
15948
|
+
* Persists the binding via ctx.settings; `active: false` on a SINGLETON cap
|
|
15949
|
+
* clears the wrapper (falling back to native if one is registered). On a
|
|
15950
|
+
* COLLECTION cap it adds to the per-device DENY set instead, and the
|
|
15951
|
+
* wrapper binding is left exactly as it was — a cap with several sources
|
|
15952
|
+
* has no "which one" for `getBindings` to answer (D556).
|
|
15953
|
+
*
|
|
15954
|
+
* `sourceId` is what makes the switch match its label. One addon can serve
|
|
15955
|
+
* several of a device's sources (`addon-provider-reolink` answers a hub
|
|
15956
|
+
* child with `native:reolink:onboard` AND `native:reolink:hub`), so a
|
|
15957
|
+
* toggle keyed by addon would turn off both while saying it turned off one
|
|
15958
|
+
* — the D62 defect with the polarity reversed (D557). Naming the source
|
|
15959
|
+
* denies exactly that source. OMITTING it keeps the cap-wide meaning
|
|
15960
|
+
* D556 shipped: every source this addon serves for this device, which is
|
|
15961
|
+
* also how a deny entry persisted before the re-key is still read.
|
|
15922
15962
|
*/
|
|
15923
15963
|
setWrapperActive: method(object({
|
|
15924
15964
|
deviceId: number(),
|
|
15925
15965
|
capName: string(),
|
|
15926
15966
|
wrapperAddonId: string(),
|
|
15967
|
+
/** The `ClipSource.source` id to toggle. Absent = all of the addon's. */
|
|
15968
|
+
sourceId: string().optional(),
|
|
15927
15969
|
active: boolean()
|
|
15928
15970
|
}), _void(), {
|
|
15929
15971
|
kind: "mutation",
|
|
@@ -27085,10 +27127,9 @@ var ServerBootModeSchema = _enum([
|
|
|
27085
27127
|
* - `idle` / `checking` / `staging` — steady / in-flight registry work.
|
|
27086
27128
|
* - `pending-restart` — a version is staged and the node has NOT yet
|
|
27087
27129
|
* restarted onto it (still running the OLD version).
|
|
27088
|
-
* - `awaiting-confirmation` —
|
|
27089
|
-
*
|
|
27090
|
-
*
|
|
27091
|
-
* manually restarted, or the probation boot auto-rolls-back.
|
|
27130
|
+
* - `awaiting-confirmation` — RETIRED with the probation boot (single-copy
|
|
27131
|
+
* collapse, 2026-07-18). Kept in the enum so an older client still parses;
|
|
27132
|
+
* no provider emits it.
|
|
27092
27133
|
*/
|
|
27093
27134
|
var ServerUpdateStateSchema = _enum([
|
|
27094
27135
|
"idle",
|
|
@@ -27177,12 +27218,35 @@ var ServerRollbackInfoSchema = object({
|
|
|
27177
27218
|
var ServerPackageStatusSchema = object({
|
|
27178
27219
|
/** Root package name (`@camstack/server` on the hub). */
|
|
27179
27220
|
packageName: string(),
|
|
27180
|
-
/**
|
|
27221
|
+
/**
|
|
27222
|
+
* Version of the code THIS PROCESS loaded — captured once, at boot, from the
|
|
27223
|
+
* package.json of the copy the code was loaded from, and never re-read. A
|
|
27224
|
+
* copy replaced on disk under a live process must not move this number;
|
|
27225
|
+
* that divergence is what `installedVersion` is for. Before 2026-09-20 this
|
|
27226
|
+
* was a lazy disk read that would have followed such a swap silently.
|
|
27227
|
+
*/
|
|
27181
27228
|
runningVersion: string().nullable(),
|
|
27182
27229
|
/** Node.js runtime version the node's process runs on (`process.versions.node`). */
|
|
27183
27230
|
nodeRuntimeVersion: string().nullable(),
|
|
27184
27231
|
/** Active data-dir root version; null when booted from seed/workspace. */
|
|
27185
27232
|
activeVersion: string().nullable(),
|
|
27233
|
+
/**
|
|
27234
|
+
* Version of the root package in the data-root `current/` copy RIGHT NOW —
|
|
27235
|
+
* what the next boot would load if nothing is staged. Normally equal to
|
|
27236
|
+
* `runningVersion`; differs only when the copy on disk changed under the
|
|
27237
|
+
* live process. `null` when there is no data-root copy (baked seed or
|
|
27238
|
+
* workspace boot). Optional for version skew: an older provider omits it.
|
|
27239
|
+
*/
|
|
27240
|
+
installedVersion: string().nullable().optional(),
|
|
27241
|
+
/**
|
|
27242
|
+
* True when the code that would run after a restart is NOT the code running
|
|
27243
|
+
* now: a version is staged (`pendingVersion`), or `installedVersion` differs
|
|
27244
|
+
* from `runningVersion`. Derived on every read, never stored. This is the
|
|
27245
|
+
* one field that lets an operator or a script say "1.2.353 is installed and
|
|
27246
|
+
* will run after a restart" instead of reading it off a number that means
|
|
27247
|
+
* "installed". Optional for version skew.
|
|
27248
|
+
*/
|
|
27249
|
+
restartRequired: boolean().optional(),
|
|
27186
27250
|
/** N-1 version kept for rollback; null when no previous version exists. */
|
|
27187
27251
|
previousVersion: string().nullable(),
|
|
27188
27252
|
/** Version of the immutable baked seed closure (image fallback). */
|
|
@@ -27217,19 +27281,71 @@ var ServerPackageStatusSchema = object({
|
|
|
27217
27281
|
});
|
|
27218
27282
|
var ServerUpdateCheckResultSchema = object({
|
|
27219
27283
|
packageName: string(),
|
|
27284
|
+
/** Same meaning as on the status payload: what THIS process loaded. */
|
|
27220
27285
|
runningVersion: string().nullable(),
|
|
27221
27286
|
latestVersion: string().nullable(),
|
|
27287
|
+
/**
|
|
27288
|
+
* `latestVersion` is newer than `runningVersion` AND is not the version
|
|
27289
|
+
* already staged on this node. A staged-and-waiting version is not "an
|
|
27290
|
+
* update available" — applying it again is refused (`already-staged`), and
|
|
27291
|
+
* a button that announced "updating…" on this boolean then got refused
|
|
27292
|
+
* would be lying. It is reported through `pendingVersion` instead.
|
|
27293
|
+
*/
|
|
27222
27294
|
updateAvailable: boolean(),
|
|
27223
27295
|
checkedAtMs: number(),
|
|
27224
27296
|
/** Non-null when the registry lookup failed (offline, bad registry, …). */
|
|
27225
|
-
error: string().nullable()
|
|
27297
|
+
error: string().nullable(),
|
|
27298
|
+
/**
|
|
27299
|
+
* Version staged on this node and awaiting its restart, when one is. Before
|
|
27300
|
+
* 2026-09-20 a check answered `{runningVersion, updateAvailable:false}` for a
|
|
27301
|
+
* node whose staged closure had never booted, and the caller had no way to
|
|
27302
|
+
* see the difference. Optional for version skew.
|
|
27303
|
+
*/
|
|
27304
|
+
pendingVersion: string().nullable().optional(),
|
|
27305
|
+
/** See the status payload: staged, or installed-on-disk ≠ running. Optional for skew. */
|
|
27306
|
+
restartRequired: boolean().optional()
|
|
27226
27307
|
});
|
|
27308
|
+
/**
|
|
27309
|
+
* What an action DID — the discriminant `accepted` cannot carry. Before
|
|
27310
|
+
* 2026-09-20 `applyServerUpdate` answered `accepted:false` both for a refusal
|
|
27311
|
+
* where nothing was wrong (already current, already staged) and for a staging
|
|
27312
|
+
* install that died on `npm error code ECONNRESET`; the only difference was
|
|
27313
|
+
* prose in `message`, and an operator restarted a container on the strength of
|
|
27314
|
+
* it, booting the previous version.
|
|
27315
|
+
*
|
|
27316
|
+
* - `staged` — the closure is installed and validated; the node
|
|
27317
|
+
* restarts to apply it (`restarting:true`). NOTHING
|
|
27318
|
+
* runs the new code until that restart completes.
|
|
27319
|
+
* - `restart-scheduled` — a plain, version-preserving restart was accepted.
|
|
27320
|
+
* - `already-current` — the target IS the running version; nothing done.
|
|
27321
|
+
* - `refused` — dropped by a gate; `reason` names which.
|
|
27322
|
+
* - `failed` — attempted and did not land; `error` says why.
|
|
27323
|
+
*/
|
|
27324
|
+
var ServerUpdateOutcomeSchema = _enum([
|
|
27325
|
+
"staged",
|
|
27326
|
+
"restart-scheduled",
|
|
27327
|
+
"already-current",
|
|
27328
|
+
"refused",
|
|
27329
|
+
"failed"
|
|
27330
|
+
]);
|
|
27227
27331
|
var ServerUpdateActionResultSchema = object({
|
|
27228
27332
|
accepted: boolean(),
|
|
27229
27333
|
targetVersion: string().nullable(),
|
|
27230
27334
|
/** True when a graceful restart was scheduled to apply the change. */
|
|
27231
27335
|
restarting: boolean(),
|
|
27232
|
-
message: string()
|
|
27336
|
+
message: string(),
|
|
27337
|
+
/** See {@link ServerUpdateOutcomeSchema}. Optional for version skew. */
|
|
27338
|
+
outcome: ServerUpdateOutcomeSchema.optional(),
|
|
27339
|
+
/**
|
|
27340
|
+
* Stable, greppable cause for `refused` / `failed` (the engine's
|
|
27341
|
+
* `UpdateRefusalReason`, `staging-failed`, …). `null` on success.
|
|
27342
|
+
*/
|
|
27343
|
+
reason: string().nullable().optional(),
|
|
27344
|
+
/**
|
|
27345
|
+
* The failure itself, verbatim enough to act on (the npm output for a
|
|
27346
|
+
* staging install). Non-null only for `failed`.
|
|
27347
|
+
*/
|
|
27348
|
+
error: string().nullable().optional()
|
|
27233
27349
|
});
|
|
27234
27350
|
var serverManagementCapability = {
|
|
27235
27351
|
name: "server-management",
|
|
@@ -28920,41 +29036,299 @@ var ClipSchema = object({
|
|
|
28920
29036
|
holes: array(object({
|
|
28921
29037
|
startMs: number(),
|
|
28922
29038
|
endMs: number()
|
|
28923
|
-
})).optional()
|
|
29039
|
+
})).optional(),
|
|
29040
|
+
/**
|
|
29041
|
+
* A URL that MAY produce this clip's still, asked only for rows actually on
|
|
29042
|
+
* screen. The opposite of {@link ClipSchema.thumbnail}: that one is VOUCHED
|
|
29043
|
+
* (a JPEG is already on disk), this one is an offer. The route answers 200
|
|
29044
|
+
* with the image, or 204 with `x-camstack-reason` when it could not mint one
|
|
29045
|
+
* — a surface latches that refusal to the instant rather than retrying.
|
|
29046
|
+
*
|
|
29047
|
+
* Never both: a clip with a vouched `thumbnail` needs no mint.
|
|
29048
|
+
*/
|
|
29049
|
+
thumbnailMint: string().optional(),
|
|
29050
|
+
/**
|
|
29051
|
+
* Why no still will be produced for this clip RIGHT NOW — set when the
|
|
29052
|
+
* provider already knows, so the surface draws the glyph and the reason
|
|
29053
|
+
* instead of firing a mint that cannot succeed.
|
|
29054
|
+
*
|
|
29055
|
+
* `sleeping` — a standalone battery camera; a read would be a wake (D549 4).
|
|
29056
|
+
* `camera-refused` — the camera answered the CoverPreview with a refusal.
|
|
29057
|
+
* `no-keyframe` — the window holds no decodable I-frame (an event that sits
|
|
29058
|
+
* inside no file is the measured case).
|
|
29059
|
+
* `unsupported` — this source cannot mint stills at all.
|
|
29060
|
+
*/
|
|
29061
|
+
thumbnailUnavailable: object({ reason: _enum([
|
|
29062
|
+
"sleeping",
|
|
29063
|
+
"camera-refused",
|
|
29064
|
+
"no-keyframe",
|
|
29065
|
+
"unsupported"
|
|
29066
|
+
]) }).optional(),
|
|
29067
|
+
/**
|
|
29068
|
+
* When the catalog this row came from was last CONFIRMED against the device.
|
|
29069
|
+
* Absent means "this row was read live". A persisted catalog served while a
|
|
29070
|
+
* camera sleeps carries the age it really has — a cached list is never drawn
|
|
29071
|
+
* as current (D549 13).
|
|
29072
|
+
*/
|
|
29073
|
+
catalogAsOf: number().optional(),
|
|
29074
|
+
/**
|
|
29075
|
+
* The camera's OWN type strings for this clip, all of them, unmapped
|
|
29076
|
+
* (`md`, `people`, `dog_cat`, `sched`, …). Kept beside {@link labels}
|
|
29077
|
+
* because a firmware inventing a type must not vanish: the mapping into our
|
|
29078
|
+
* filter vocabulary is lossy on purpose and this is the lossless copy
|
|
29079
|
+
* (D549 20).
|
|
29080
|
+
*/
|
|
29081
|
+
nativeTypes: array(string()).optional(),
|
|
29082
|
+
/**
|
|
29083
|
+
* What the subject DID — `crossline`, `intrude`, `loitering`. A behaviour
|
|
29084
|
+
* travels BESIDE a class, never instead of one, and the class filter ignores
|
|
29085
|
+
* it: "a person crossed a line" is still a person (D549 20).
|
|
29086
|
+
*/
|
|
29087
|
+
behaviours: array(string()).optional(),
|
|
29088
|
+
/**
|
|
29089
|
+
* The same recording as two files — the sub twin (what the row and its
|
|
29090
|
+
* thumbnail are) and its main twin, matched at listing time so a quality
|
|
29091
|
+
* change never re-searches the camera (D549 15). `getClipPlayback`'s
|
|
29092
|
+
* `profile` picks between them: `low | mid` → sub, `high` → main.
|
|
29093
|
+
*/
|
|
29094
|
+
streams: object({
|
|
29095
|
+
sub: object({
|
|
29096
|
+
id: string(),
|
|
29097
|
+
bytes: number().optional()
|
|
29098
|
+
}).optional(),
|
|
29099
|
+
main: object({
|
|
29100
|
+
id: string(),
|
|
29101
|
+
bytes: number().optional()
|
|
29102
|
+
}).optional()
|
|
29103
|
+
}).optional(),
|
|
29104
|
+
/** The camera says it holds a sub-stream copy of this recording. */
|
|
29105
|
+
supportSub: boolean().optional(),
|
|
29106
|
+
/**
|
|
29107
|
+
* Whether this row has bytes behind it. ABSENT means yes — every clip that
|
|
29108
|
+
* IS a file is playable, and only a source that lists EVENTS can produce a
|
|
29109
|
+
* row with nothing to play (the measured case: 1 of 29 hub events on 3628
|
|
29110
|
+
* fell inside no file). Such a row is shown, never dropped and never offered
|
|
29111
|
+
* as playable-then-failing (D549 19).
|
|
29112
|
+
*/
|
|
29113
|
+
playable: boolean().optional(),
|
|
29114
|
+
/** Why {@link playable} is false, verbatim (`no-file-for-window`). */
|
|
29115
|
+
unplayableReason: string().optional()
|
|
28924
29116
|
});
|
|
28925
29117
|
var ClipPlaybackSchema = object({
|
|
28926
|
-
/**
|
|
29118
|
+
/**
|
|
29119
|
+
* A media URL through the hub data-plane. {@link ClipPlaybackSchema.format}
|
|
29120
|
+
* says what kind — an HLS master playlist for a recording-derived clip, a
|
|
29121
|
+
* progressive MP4 for a native file the vendor addon muxed and serves with
|
|
29122
|
+
* `Range`. The URL is NOT a credential: both planes are registered
|
|
29123
|
+
* `access: 'authenticated'` and the hub's `/addon/<id>/<prefix>` proxy takes
|
|
29124
|
+
* the session cookie, so nothing is appended to it (D549 22).
|
|
29125
|
+
*/
|
|
28927
29126
|
playbackUrl: string(),
|
|
29127
|
+
/**
|
|
29128
|
+
* How to play {@link playbackUrl}. Absent means `hls` — the shape every
|
|
29129
|
+
* existing consumer already assumes. A player that branches on this is the
|
|
29130
|
+
* one change a native clip needs; a player that ignores it will hand an MP4
|
|
29131
|
+
* to hls.js and fail parsing it as a manifest.
|
|
29132
|
+
*/
|
|
29133
|
+
format: _enum(["hls", "mp4"]).optional(),
|
|
29134
|
+
/**
|
|
29135
|
+
* Which twin was actually served. A clip that holds only one stream answers
|
|
29136
|
+
* with the one it has, and the surface SAYS so — a missing main twin is
|
|
29137
|
+
* never served silently as if it were the asked-for quality (D549 15).
|
|
29138
|
+
*/
|
|
29139
|
+
served: CamProfileSchema.optional(),
|
|
28928
29140
|
/** Optional LAN/remote alternates for the same clip. */
|
|
28929
29141
|
playbackEndpoints: array(string()).optional(),
|
|
28930
29142
|
token: string().optional()
|
|
28931
29143
|
});
|
|
29144
|
+
/**
|
|
29145
|
+
* Why a source cannot answer right now — per SOURCE, never fleet-wide.
|
|
29146
|
+
*
|
|
29147
|
+
* `ok` is the only state whose clip list may be read as complete. The other
|
|
29148
|
+
* three exist because an empty list from a sleeping camera reads as "this
|
|
29149
|
+
* camera has no recordings", which is the defect this whole line of work is
|
|
29150
|
+
* about: a battery camera nobody woke (`sleeping`), a camera that could not be
|
|
29151
|
+
* reached at all (`unreachable`, also what a provider that THREW reports), a
|
|
29152
|
+
* camera whose SD card is not mounted (`no-storage`, measured on 640 —
|
|
29153
|
+
* `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
|
|
29154
|
+
* camera whose OWN index disagrees with its OWN calendar (`index-empty`,
|
|
29155
|
+
* measured on 618: the calendar marks 3–20 September, days 6–20 list zero
|
|
29156
|
+
* files on both streams and both filters, with 177 GB free). That last one is
|
|
29157
|
+
* a defect ON THE CAMERA, and the only honest thing a provider can do is say
|
|
29158
|
+
* which days it asked for and got nothing — "no clips" would be a lie about a
|
|
29159
|
+
* card that is full of them.
|
|
29160
|
+
*/
|
|
29161
|
+
var ClipSourceAvailabilitySchema = object({
|
|
29162
|
+
state: _enum([
|
|
29163
|
+
"ok",
|
|
29164
|
+
"sleeping",
|
|
29165
|
+
"unreachable",
|
|
29166
|
+
"no-storage",
|
|
29167
|
+
"index-empty"
|
|
29168
|
+
]),
|
|
29169
|
+
/** Free text, shown verbatim. Names the camera's own refusal when there is one. */
|
|
29170
|
+
reason: string().optional(),
|
|
29171
|
+
/** When this source's catalog was last CONFIRMED. A cached list is never
|
|
29172
|
+
* drawn as current: the surface shows the age whenever it is older than the
|
|
29173
|
+
* refresh interval. */
|
|
29174
|
+
catalogAsOf: number().optional()
|
|
29175
|
+
});
|
|
29176
|
+
/**
|
|
29177
|
+
* One SOURCE of clips for a camera — a row of the picker, and the namespace
|
|
29178
|
+
* every clip id from it is prefixed with (`analytics`,
|
|
29179
|
+
* `native:reolink:onboard`, `hksv`, …).
|
|
29180
|
+
*
|
|
29181
|
+
* A provider lists the sources IT serves for that device, and answers for each
|
|
29182
|
+
* of them whether it can answer at all. A provider with nothing to offer on a
|
|
29183
|
+
* camera returns `[]` — it is not that camera's business.
|
|
29184
|
+
*/
|
|
29185
|
+
var ClipSourceSchema = object({
|
|
29186
|
+
/** The value this source stamps on {@link ClipSchema.source}, and the prefix
|
|
29187
|
+
* of every clip id it mints. `getClipPlayback` routes on it. */
|
|
29188
|
+
source: string(),
|
|
29189
|
+
/** Operator-facing name of the source ("CamStack recordings", "SD card"). */
|
|
29190
|
+
label: string(),
|
|
29191
|
+
/**
|
|
29192
|
+
* The addon that SERVES this row.
|
|
29193
|
+
*
|
|
29194
|
+
* A surface cannot otherwise resolve a source to who answers it, and the
|
|
29195
|
+
* alternative — a `native:reolink:* → provider-reolink` table inside the
|
|
29196
|
+
* widget — is a second authority on provider identity living in the one
|
|
29197
|
+
* package with no business knowing it, wrong the day a third source appears
|
|
29198
|
+
* (D557). One addon may serve SEVERAL sources: `addon-provider-reolink`
|
|
29199
|
+
* answers a hub child with both `native:reolink:onboard` and
|
|
29200
|
+
* `native:reolink:hub`, which is why the per-device switch is keyed by
|
|
29201
|
+
* SOURCE and not by this (D555).
|
|
29202
|
+
*
|
|
29203
|
+
* Optional for version skew only. The collection dispatcher stamps it from
|
|
29204
|
+
* the registry, so a row that travelled through the fan-out carries the
|
|
29205
|
+
* authoritative id whatever the provider filled in.
|
|
29206
|
+
*/
|
|
29207
|
+
addonId: string().optional(),
|
|
29208
|
+
/**
|
|
29209
|
+
* Which API this source resolved to FOR THIS CAMERA, when it has a choice.
|
|
29210
|
+
*
|
|
29211
|
+
* A source may cover one store through more than one surface — the Reolink
|
|
29212
|
+
* provider reads a hub child through the parent's event log and a standalone
|
|
29213
|
+
* through its own file list, because that is what each camera answers. The
|
|
29214
|
+
* CHOICE is the provider's, made from what the camera is, and is never a row
|
|
29215
|
+
* the operator has to understand; but it is REPORTED, because a source that
|
|
29216
|
+
* silently reads a different API on two cameras and then behaves differently
|
|
29217
|
+
* is the thing nobody can debug later. Absent when the source has only one
|
|
29218
|
+
* way to read its store.
|
|
29219
|
+
*/
|
|
29220
|
+
via: string().optional(),
|
|
29221
|
+
availability: ClipSourceAvailabilitySchema,
|
|
29222
|
+
/**
|
|
29223
|
+
* The operator switched this source OFF for this camera.
|
|
29224
|
+
*
|
|
29225
|
+
* Deliberately NOT a member of {@link ClipSourceAvailabilitySchema}'s
|
|
29226
|
+
* vocabulary. That enum models what the source CAN do — a sleeping camera, an
|
|
29227
|
+
* unmounted card, an index that disagrees with its own calendar — and a
|
|
29228
|
+
* switched-off source could answer perfectly well; the operator decided it
|
|
29229
|
+
* should not. Folding the choice in is how `disabled` and `broken` stop being
|
|
29230
|
+
* distinguishable, which is the D62 rule this repo has already paid for twice:
|
|
29231
|
+
* an off switch is REPORTED off (`CameraStatus.switchedOff`, the same word),
|
|
29232
|
+
* and disabled must never look like broken. It is also what lets every
|
|
29233
|
+
* exhaustive consumer of the availability enum keep compiling.
|
|
29234
|
+
*
|
|
29235
|
+
* A switched-off source contributes NO clips (`listClips` never calls it) and
|
|
29236
|
+
* its row carries no `catalogAsOf`: nothing confirms a catalog it is not
|
|
29237
|
+
* allowed to serve, and a frozen age that can only grow draws a stalling
|
|
29238
|
+
* source rather than an off switch.
|
|
29239
|
+
*
|
|
29240
|
+
* The row survives BECAUSE it is the control the operator switches the source
|
|
29241
|
+
* back on from — D554 decision 4's rule ("a source that cannot answer
|
|
29242
|
+
* produces a ROW, not an absence") applied to the one case D556 carved out of
|
|
29243
|
+
* it, and D557's own kept property ("a source is never hidden, only its
|
|
29244
|
+
* rows"). Absent means on.
|
|
29245
|
+
*
|
|
29246
|
+
* A provider never sets this — like {@link ClipSourceSchema.addonId} it is
|
|
29247
|
+
* stamped by the collection dispatcher, which holds the registry's projection
|
|
29248
|
+
* of the persisted authority (D556) and is the only place that knows it.
|
|
29249
|
+
*/
|
|
29250
|
+
switchedOff: boolean().optional()
|
|
29251
|
+
});
|
|
28932
29252
|
var videoclipsCapability = {
|
|
28933
29253
|
name: "videoclips",
|
|
28934
29254
|
scope: "device",
|
|
28935
|
-
mode: "
|
|
29255
|
+
mode: "collection",
|
|
28936
29256
|
kind: "wrapper",
|
|
28937
29257
|
defaultActive: true,
|
|
28938
29258
|
/** A clip is a window over a camera's footage — the cap is meaningless on a
|
|
28939
29259
|
* sensor, a button or an event emitter, and the `defaultActive` auto-bind
|
|
28940
29260
|
* reads this to decide which devices it may claim. */
|
|
28941
29261
|
deviceTypes: [DeviceType.Camera],
|
|
29262
|
+
/**
|
|
29263
|
+
* The Clips section of a camera's device details is FRAMEWORK-DERIVED (D14):
|
|
29264
|
+
* the aggregator turns this declaration into the `type:'widget'` section and
|
|
29265
|
+
* `DeviceDetail.tsx` is never edited. `videoclips` is the first WRAPPER cap
|
|
29266
|
+
* to declare one — every previous `host/` widget cap is `deviceNative` — so
|
|
29267
|
+
* `device-config-widget-wrapped-binding.spec.ts` pins that a `kind:'wrapped'`
|
|
29268
|
+
* binding entry derives the same section a native one does.
|
|
29269
|
+
*
|
|
29270
|
+
* `topTab` because the browser owns the whole pane (a day's clips, a source
|
|
29271
|
+
* list and a player), exactly as `ptz` does; the widget itself is
|
|
29272
|
+
* `host/clips-browser` in ui-library's `HOST_WIDGETS`.
|
|
29273
|
+
*/
|
|
29274
|
+
deviceConfig: { ui: {
|
|
29275
|
+
kind: "widget",
|
|
29276
|
+
widgetId: "host/clips-browser",
|
|
29277
|
+
tab: "clips",
|
|
29278
|
+
topTab: true,
|
|
29279
|
+
label: "Clips",
|
|
29280
|
+
order: 0
|
|
29281
|
+
} },
|
|
28942
29282
|
methods: {
|
|
28943
29283
|
listClips: method(object({
|
|
28944
29284
|
deviceId: number(),
|
|
28945
29285
|
since: number(),
|
|
28946
29286
|
until: number(),
|
|
28947
|
-
limit: number().int().positive().optional()
|
|
29287
|
+
limit: number().int().positive().optional(),
|
|
29288
|
+
/**
|
|
29289
|
+
* View filter over {@link ClipSourceSchema.source} values — the
|
|
29290
|
+
* picker's selection, forwarded so a provider need not list what
|
|
29291
|
+
* nobody is looking at. ABSENT means every source this camera has,
|
|
29292
|
+
* which is the honest default for a surface whose whole point is that
|
|
29293
|
+
* nothing is hidden (D554 3). A provider with one source ignores it.
|
|
29294
|
+
*/
|
|
29295
|
+
sources: array(string()).optional()
|
|
28948
29296
|
}), array(ClipSchema).readonly(), {
|
|
28949
29297
|
kind: "query",
|
|
28950
|
-
auth: "
|
|
29298
|
+
auth: "protected"
|
|
29299
|
+
}),
|
|
29300
|
+
/**
|
|
29301
|
+
* The sources this camera has, WITH the reason any of them cannot answer.
|
|
29302
|
+
*
|
|
29303
|
+
* Asked separately from `listClips` because an empty clip list is
|
|
29304
|
+
* ambiguous and this is the only place the ambiguity is resolved: every
|
|
29305
|
+
* bound provider contributes its own rows, and a provider that could not
|
|
29306
|
+
* be reached at all still produces one row saying so. A surface that draws
|
|
29307
|
+
* "no clips" without reading this is drawing a guess.
|
|
29308
|
+
*/
|
|
29309
|
+
listSources: method(object({ deviceId: number() }), array(ClipSourceSchema).readonly(), {
|
|
29310
|
+
kind: "query",
|
|
29311
|
+
auth: "protected"
|
|
28951
29312
|
}),
|
|
28952
29313
|
getClipPlayback: method(object({
|
|
28953
29314
|
deviceId: number(),
|
|
28954
|
-
clipId: string()
|
|
29315
|
+
clipId: string(),
|
|
29316
|
+
/**
|
|
29317
|
+
* Which twin to serve, on the ONE quality scale the system already has
|
|
29318
|
+
* (`CamProfileSchema`). `low | mid` → the sub file, `high` → the main
|
|
29319
|
+
* twin; both ids are already on the row so this never re-searches the
|
|
29320
|
+
* camera. Absent means the provider's own default (the sub file, which
|
|
29321
|
+
* every source is measured to hold).
|
|
29322
|
+
*
|
|
29323
|
+
* `auto` is deliberately NOT accepted here: a stored file has no
|
|
29324
|
+
* broker session, so the adaptive tier cannot be resolved for it. The
|
|
29325
|
+
* viewer resolves `auto` to a profile the same way live does, before
|
|
29326
|
+
* it calls (D549 15).
|
|
29327
|
+
*/
|
|
29328
|
+
profile: CamProfileSchema.optional()
|
|
28955
29329
|
}), ClipPlaybackSchema, {
|
|
28956
29330
|
kind: "query",
|
|
28957
|
-
auth: "
|
|
29331
|
+
auth: "protected"
|
|
28958
29332
|
})
|
|
28959
29333
|
}
|
|
28960
29334
|
};
|
|
@@ -47048,6 +47422,12 @@ Object.freeze({
|
|
|
47048
47422
|
addonId: null,
|
|
47049
47423
|
access: "view"
|
|
47050
47424
|
},
|
|
47425
|
+
"videoclips.listSources": {
|
|
47426
|
+
capName: "videoclips",
|
|
47427
|
+
capScope: "device",
|
|
47428
|
+
addonId: null,
|
|
47429
|
+
access: "view"
|
|
47430
|
+
},
|
|
47051
47431
|
"viewerUi.getStaticDir": {
|
|
47052
47432
|
capName: "viewer-ui",
|
|
47053
47433
|
capScope: "system",
|
|
@@ -49056,6 +49436,11 @@ Object.freeze({
|
|
|
49056
49436
|
form: "single",
|
|
49057
49437
|
optional: false
|
|
49058
49438
|
}],
|
|
49439
|
+
"videoclips.listSources": [{
|
|
49440
|
+
name: "deviceId",
|
|
49441
|
+
form: "single",
|
|
49442
|
+
optional: false
|
|
49443
|
+
}],
|
|
49059
49444
|
"waterHeater.setAway": [{
|
|
49060
49445
|
name: "deviceId",
|
|
49061
49446
|
form: "single",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h as e, l as t, u as n, y as r } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-Bs1t18EM.mjs";
|
|
2
|
-
import { o as i, s as a } from "./responsive-
|
|
2
|
+
import { o as i, s as a } from "./responsive-CC0j2h-d.mjs";
|
|
3
3
|
import { n as o, r as s, t as c } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
|
|
4
4
|
var l = a("chevron-down", [["path", {
|
|
5
5
|
d: "m6 9 6 6 6-6",
|
package/dist/remoteEntry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-
|
|
1
|
+
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-D8j_yb3G.mjs";
|
|
2
2
|
export { t as get, e as init };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as e, g as t, h as n, l as r, n as i, p as a, r as o, t as s, u as c, y as l } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-Bs1t18EM.mjs";
|
|
2
2
|
import "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
|
|
3
|
-
import { n as u } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
3
|
+
import { n as u } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BK-eslgm.mjs";
|
|
4
4
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
|
|
5
5
|
l();
|
|
6
6
|
var d = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), f = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), p = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), m = (e) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as e, h as t, p as n, y as r } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-Bs1t18EM.mjs";
|
|
2
|
-
import { s as i } from "./responsive-
|
|
2
|
+
import { s as i } from "./responsive-CC0j2h-d.mjs";
|
|
3
3
|
var a = i("camera", [["path", {
|
|
4
4
|
d: "M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",
|
|
5
5
|
key: "18u6gg"
|
|
@@ -2753,7 +2753,7 @@ async function rr(e) {
|
|
|
2753
2753
|
}
|
|
2754
2754
|
}
|
|
2755
2755
|
async function ir() {
|
|
2756
|
-
return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-
|
|
2756
|
+
return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-B2cBM7jE.mjs")).catch((e) => {
|
|
2757
2757
|
throw tr = void 0, e;
|
|
2758
2758
|
}), tr;
|
|
2759
2759
|
}
|