@camstack/addon-admin-ui 1.2.298 → 1.2.300
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/assets/{AddonCollectionPage-Df7TFa8c.js → AddonCollectionPage-Cr-KfwvP.js} +1 -1
- package/dist/assets/{Addons-BL0l83HX.js → Addons-DoAs_KfP.js} +1 -1
- package/dist/assets/{AdminTabs-_3rYGvff.js → AdminTabs-nO86C-du.js} +1 -1
- package/dist/assets/{AiProfiles-Cb_Zmt2e.js → AiProfiles-DZuK8h7D.js} +1 -1
- package/dist/assets/{BrokerForm-O4qx5NOl.js → BrokerForm-MOPaJ62m.js} +1 -1
- package/dist/assets/Build-fVZjJtBq.js +32 -0
- package/dist/assets/{Capabilities-BhWA9I3U.js → Capabilities-5vhoPQFd.js} +1 -1
- package/dist/assets/{CapabilityBadges-E822NR6-.js → CapabilityBadges-CJnsp_LH.js} +1 -1
- package/dist/assets/{Cluster-CytT6oOR.js → Cluster-BsbJ3J5p.js} +2 -2
- package/dist/assets/CompositionEditor-DbDCjW1s.js +1 -0
- package/dist/assets/{CompositionEditorPage-D-Pr98e9.js → CompositionEditorPage-BfvnF5_n.js} +1 -1
- package/dist/assets/{Data-C_5nuknP.js → Data-DqV6ClEA.js} +1 -1
- package/dist/assets/{DetectionIntelligence-Ddu_ubPT.js → DetectionIntelligence-XPzIfD-8.js} +1 -1
- package/dist/assets/{DeviceAggregateSection-kHgMnzdV.js → DeviceAggregateSection-CG9OIoVb.js} +1 -1
- package/dist/assets/DeviceDetail-BfbO3V0b.js +2 -0
- package/dist/assets/{Devices-CkDDnlUY.js → Devices-Dq_iXMXN.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-4bKTeu-8.js → EmbedPlayerPage-CY5PDgte.js} +1 -1
- package/dist/assets/Events-BeWVGaev.js +1 -0
- package/dist/assets/{FormBuilder-DFkvqrJD.js → FormBuilder-B8jus43Y.js} +1 -1
- package/dist/assets/{Identity-Bs0HMUZv.js → Identity-DaJyz-ig.js} +1 -1
- package/dist/assets/IntegrationDetail-mee6rfl4.js +1 -0
- package/dist/assets/Integrations-DTrUecHI.js +1 -0
- package/dist/assets/{Integrations-D5LYSgWQ.js → Integrations-e_CGcE53.js} +1 -1
- package/dist/assets/Locations-naeoUiMl.js +3 -0
- package/dist/assets/{Logs-CdSMPoxV.js → Logs-DHvS0ZG4.js} +1 -1
- package/dist/assets/{ModelLicenses-GuvIn1gk.js → ModelLicenses-CHF6ETO5.js} +1 -1
- package/dist/assets/{MotionZonesSettings-C5cymw6R.js → MotionZonesSettings-DveHRZ1M.js} +1 -1
- package/dist/assets/{MyAccess-DKvcVvYi.js → MyAccess-ZmbQ_xfb.js} +1 -1
- package/dist/assets/{Network-DO7j65It.js → Network-C4frL_HE.js} +1 -1
- package/dist/assets/{NodeAddonsSettingsPanel-Bj_BK8BK.js → NodeAddonsSettingsPanel-11F3P0IK.js} +1 -1
- package/dist/assets/{NodeInferenceDevices-DEF7iUIy.js → NodeInferenceDevices-B7lbdDTW.js} +1 -1
- package/dist/assets/Notifications-DRLYWjDS.js +1 -0
- package/dist/assets/{Pipeline-C3rd2o0z.js → Pipeline-qSnWQmZ4.js} +1 -1
- package/dist/assets/{Plates-KK9Jucpy.js → Plates-B0u-1Qcz.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-DLWoWKa1.js → PrivacyMaskSettings-CWYULq-y.js} +1 -1
- package/dist/assets/{ProviderIcon-B95H0OGs.js → ProviderIcon-DAp_lMDw.js} +1 -1
- package/dist/assets/{Recordings-BIMt47G_.js → Recordings-fNBcOSUc.js} +1 -1
- package/dist/assets/{ScanNetworkModal-C745HgYN.js → ScanNetworkModal-xnOiLGgg.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-DEFeKrQi.js → SceneMonitorEditor-gDpt6iKo.js} +1 -1
- package/dist/assets/{Scenes-31t1OF8h.js → Scenes-DDAmEqU9.js} +1 -1
- package/dist/assets/{Settings-rfP-ZvI0.js → Settings-Dv_5fVj2.js} +1 -1
- package/dist/assets/{Showroom-Df8NV8QK.js → Showroom-B7D-nKLt.js} +1 -1
- package/dist/assets/{StorageLocationsPanel-DGsk0Ute.js → StorageLocationsPanel-BZ5j8c1h.js} +1 -1
- package/dist/assets/{Terminal-CDJOGeqz.js → Terminal-DR0RmRD6.js} +1 -1
- package/dist/assets/{Viewer-BjRST1rI.js → Viewer-Cg7A1w4F.js} +1 -1
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-C4tT4btJ.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-TK7cnRbq.js} +1 -1
- package/dist/assets/{archive-TrxiLNcl.js → archive-CCEAH2-E.js} +1 -1
- package/dist/assets/{authed-media-CH1U0Z7I.js → authed-media-ClZ80rNx.js} +1 -1
- package/dist/assets/{boxes-BAiYOams.js → boxes-BdtZgTjz.js} +1 -1
- package/dist/assets/circle-slash-CgvI8iSv.js +1 -0
- package/dist/assets/{debounced-invalidate-BDeU9yPQ.js → debounced-invalidate-C2eb-Tqo.js} +1 -1
- package/dist/assets/{device-integration-icon-CHkYoY0a.js → device-integration-icon-Ck2Y2lL5.js} +1 -1
- package/dist/assets/device-picker-model-qVKFWw6-.js +1 -0
- package/dist/assets/dist-BXj5mC45.js +349 -0
- package/dist/assets/{dist-a0ex8Xy3.js → dist-Cjkv3uUk.js} +1 -1
- package/dist/assets/{face-bbox-BO4f9HS4.js → face-bbox-Co5b1ky_.js} +1 -1
- package/dist/assets/{hard-drive-download-DMTgloj5.js → hard-drive-download-ep0y7LyP.js} +1 -1
- package/dist/assets/{hostInit-DImvGASf.js → hostInit-BoAo3PhF.js} +1 -1
- package/dist/assets/{index-CgXPc-AV.js → index-C_wdx2NZ.js} +3 -3
- package/dist/assets/index-egLHRpbu.css +2 -0
- package/dist/assets/{layers-eROspUmA.js → layers-BU-FWaJU.js} +1 -1
- package/dist/assets/{location-owned-usage-sOE3xLhc.js → location-owned-usage-C3ej6Pj6.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-84890b2e.js → mf-entry-bootstrap-0-50975fe6.js} +2 -2
- package/dist/assets/{player-overlays-o54P23P2.js → player-overlays-CjhGPGRH.js} +1 -1
- package/dist/assets/remoteEntry-C2_I-Of1.js +1 -0
- package/dist/assets/{send-D0d5eZ61.js → send-CEk5WYNt.js} +1 -1
- package/dist/assets/{settings-2-Dqj-Whfr.js → settings-2-MB6Thalh.js} +1 -1
- package/dist/assets/{square-check-big-CC2dU6RF.js → square-check-big-ZL-AwzeA.js} +1 -1
- package/dist/assets/src-BiDz1hgC.js +67 -0
- package/dist/assets/src-bXB9J58r.js +349 -0
- package/dist/assets/{use-scenes-feed-R-GEBDBU.js → use-scenes-feed-CwP86V7k.js} +1 -1
- package/dist/assets/{use-stationary-objects-CO4PdIFG.js → use-stationary-objects-eBMDdhXW.js} +1 -1
- package/dist/assets/{useDevice-BU0imY9B.js → useDevice-CGj-WKTC.js} +1 -1
- package/dist/assets/useEventInvalidation-BaNmc7Ke.js +1 -0
- package/dist/assets/{useNodeUrlSelection-Dlf0CWPU.js → useNodeUrlSelection-DMCMMjaf.js} +1 -1
- package/dist/assets/user-round-CqtnExEW.js +1 -0
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-DAaE-Myc.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-Dt6rtuC7.js} +2 -2
- package/dist/index.html +6 -6
- package/dist/server/addon.js +235 -102
- package/package.json +1 -1
- package/dist/assets/Build-CNQhG6ma.js +0 -32
- package/dist/assets/CompositionEditor-BhWVT7RV.js +0 -1
- package/dist/assets/DeviceDetail-BZJKkllF.js +0 -2
- package/dist/assets/Events-DoN_tLnP.js +0 -1
- package/dist/assets/IntegrationDetail-Cr5-tJiw.js +0 -1
- package/dist/assets/Integrations-D5hX1u4b.js +0 -1
- package/dist/assets/Locations-NysPu2nw.js +0 -3
- package/dist/assets/Notifications-R4TlE5EH.js +0 -1
- package/dist/assets/circle-slash-Di12V3ul.js +0 -1
- package/dist/assets/dist-3HV5hQQl.js +0 -349
- package/dist/assets/index-DOZUgTMC.css +0 -2
- package/dist/assets/remoteEntry-nDKnWQvr.js +0 -1
- package/dist/assets/src-C36-vO5A.js +0 -349
- package/dist/assets/src-f3OJiuN1.js +0 -67
- package/dist/assets/useEventInvalidation-BxCnrh5u.js +0 -1
- package/dist/assets/user-round-CXdkrmGZ.js +0 -1
package/dist/server/addon.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -533,6 +533,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
533
533
|
*/
|
|
534
534
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
535
535
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
536
|
+
/**
|
|
537
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
538
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
539
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
540
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
541
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
542
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
543
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
544
|
+
*/
|
|
536
545
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
537
546
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
538
547
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -5371,7 +5380,7 @@ var ZodIssueCode = {
|
|
|
5371
5380
|
var ZodFirstPartyTypeKind;
|
|
5372
5381
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5373
5382
|
//#endregion
|
|
5374
|
-
//#region ../types/dist/sleep-
|
|
5383
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
5375
5384
|
/**
|
|
5376
5385
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5377
5386
|
* window to float samples (D455).
|
|
@@ -7418,7 +7427,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
7418
7427
|
return DeviceRole;
|
|
7419
7428
|
}({});
|
|
7420
7429
|
//#endregion
|
|
7421
|
-
//#region ../types/dist/composition-
|
|
7430
|
+
//#region ../types/dist/composition-43aqsZQj.mjs
|
|
7422
7431
|
/**
|
|
7423
7432
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7424
7433
|
*
|
|
@@ -7475,13 +7484,12 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
|
|
|
7475
7484
|
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
7476
7485
|
* valutatore puro del suo FRONTE.
|
|
7477
7486
|
*
|
|
7478
|
-
*
|
|
7479
|
-
*
|
|
7480
|
-
*
|
|
7481
|
-
*
|
|
7482
|
-
*
|
|
7483
|
-
* fa suonare il campanello ma non registra" — è esattamente D62.
|
|
7484
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7487
|
+
* UNA tabella per tutti quelli che chiedono "questo device è ALTO?": il
|
|
7488
|
+
* trigger `RecordingTriggers.sensorDeviceIds` del recorder, i marker dei
|
|
7489
|
+
* sensori della post-analysis, il bridge camera-sensors dell'orchestratore e
|
|
7490
|
+
* le sorgenti di un campanello composto (`doorbellFeatureSources`, D671).
|
|
7491
|
+
* Una seconda copia divergerebbe alla prima cap aggiunta, e il sintomo — "il
|
|
7492
|
+
* sensore fa suonare il campanello ma non registra" — è esattamente D62.
|
|
7485
7493
|
*
|
|
7486
7494
|
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
7487
7495
|
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
@@ -9216,7 +9224,7 @@ var RecordingTriggersSchema = object({
|
|
|
9216
9224
|
*
|
|
9217
9225
|
* Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
|
|
9218
9226
|
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
|
|
9219
|
-
* la stessa
|
|
9227
|
+
* la stessa del campanello composto (D671). Ed è il FRONTE, non
|
|
9220
9228
|
* il livello: un contatto trovato già aperto al riavvio del runner non fa
|
|
9221
9229
|
* registrare.
|
|
9222
9230
|
*/
|
|
@@ -15302,28 +15310,10 @@ method(object({
|
|
|
15302
15310
|
deviceIds: array(number()).readonly(),
|
|
15303
15311
|
caps: array(string()).readonly().optional()
|
|
15304
15312
|
}), record(string(), record(string(), unknown().nullable())));
|
|
15305
|
-
|
|
15306
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
15307
|
-
lastPressedAt: number().nullable(),
|
|
15308
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
15309
|
-
pressCountSinceStart: number()
|
|
15310
|
-
});
|
|
15311
|
-
object({
|
|
15312
|
-
deviceId: number(),
|
|
15313
|
-
timestamp: number()
|
|
15314
|
-
});
|
|
15315
|
-
/**
|
|
15316
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
15317
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
15318
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
15319
|
-
*/
|
|
15320
|
-
var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
|
|
15313
|
+
var ExtensionSlotIdSchema = _enum(["linked-devices"]);
|
|
15321
15314
|
DeviceType.Camera;
|
|
15322
|
-
DeviceType.Button, DeviceType.Camera;
|
|
15323
|
-
var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
|
|
15324
|
-
DeviceType.Camera, DeviceType.Camera;
|
|
15325
15315
|
/** A slot's editable value, discriminated on `slot`. */
|
|
15326
|
-
var ExtensionSlotValueSchema = discriminatedUnion("slot", [
|
|
15316
|
+
var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
|
|
15327
15317
|
DeviceType.Camera;
|
|
15328
15318
|
var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
|
|
15329
15319
|
state: literal("unreachable"),
|
|
@@ -15360,10 +15350,11 @@ var ExtensionSlotSourceSchema = object({
|
|
|
15360
15350
|
});
|
|
15361
15351
|
/**
|
|
15362
15352
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
15363
|
-
* reported read-only, named, never written through this contract (D62).
|
|
15364
|
-
*
|
|
15365
|
-
*
|
|
15366
|
-
* `unknown` means the gate could
|
|
15353
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
15354
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
15355
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
15356
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
15357
|
+
* not be read; it is not "inactive" (D315).
|
|
15367
15358
|
*/
|
|
15368
15359
|
var ExtensionSlotActivationSchema = object({
|
|
15369
15360
|
state: _enum([
|
|
@@ -15379,7 +15370,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
|
|
|
15379
15370
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
15380
15371
|
slotRef: string(),
|
|
15381
15372
|
slot: ExtensionSlotIdSchema,
|
|
15382
|
-
/** Names the store written (D62), e.g. `
|
|
15373
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
15383
15374
|
authority: string(),
|
|
15384
15375
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
15385
15376
|
value: ExtensionSlotValueSchema,
|
|
@@ -19864,6 +19855,29 @@ object({
|
|
|
19864
19855
|
firstAt: number(),
|
|
19865
19856
|
lastAt: number()
|
|
19866
19857
|
});
|
|
19858
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
19859
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
19860
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
19861
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
19862
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
19863
|
+
mode: AlarmArmModeSchema,
|
|
19864
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
19865
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
19866
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
19867
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
19868
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
19869
|
+
mode: AlarmArmModeSchema,
|
|
19870
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
19871
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
19872
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
19873
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
19874
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
19875
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
19876
|
+
mode: AlarmArmModeSchema,
|
|
19877
|
+
deviceId: number().int().positive(),
|
|
19878
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
19879
|
+
nonBlocking: boolean()
|
|
19880
|
+
});
|
|
19867
19881
|
/**
|
|
19868
19882
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
19869
19883
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -19872,10 +19886,10 @@ object({
|
|
|
19872
19886
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
19873
19887
|
mode: AlarmArmModeSchema,
|
|
19874
19888
|
deviceIds: array(number().int()).max(200)
|
|
19875
|
-
})).max(8).refine(
|
|
19889
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
19876
19890
|
/**
|
|
19877
|
-
* The three durations
|
|
19878
|
-
* transitions, and which openings each mode tolerates.
|
|
19891
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
19892
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
19879
19893
|
*
|
|
19880
19894
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
19881
19895
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -19885,15 +19899,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
19885
19899
|
*/
|
|
19886
19900
|
var NcAlarmSettingsSchema = object({
|
|
19887
19901
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
19888
|
-
exitDelaySec:
|
|
19902
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
19889
19903
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
19890
|
-
entryDelaySec:
|
|
19904
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
19891
19905
|
/**
|
|
19892
19906
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
19893
19907
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
19894
19908
|
* existed, and therefore what an untouched install keeps doing.
|
|
19895
19909
|
*/
|
|
19896
|
-
triggeredDurationSec:
|
|
19910
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
19897
19911
|
/**
|
|
19898
19912
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
19899
19913
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -19916,17 +19930,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
19916
19930
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
19917
19931
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
19918
19932
|
*/
|
|
19919
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
19933
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
19934
|
+
/**
|
|
19935
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
19936
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
19937
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
19938
|
+
*/
|
|
19939
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
19920
19940
|
});
|
|
19921
19941
|
/**
|
|
19922
19942
|
* Every field optional — a tab edits one control at a time.
|
|
19923
19943
|
*
|
|
19924
|
-
* `nonBlocking`
|
|
19925
|
-
* remove an inner `.default()`, so a patch that never
|
|
19926
|
-
* parse to `
|
|
19927
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
19944
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
19945
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
19946
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
19947
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
19948
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
19928
19949
|
*/
|
|
19929
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
19950
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
19951
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
19952
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
19953
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
19954
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
19955
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
19956
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
19930
19957
|
/**
|
|
19931
19958
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
19932
19959
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20026,6 +20053,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20026
20053
|
*/
|
|
20027
20054
|
live: NcAlarmLiveSchema.optional()
|
|
20028
20055
|
});
|
|
20056
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20057
|
+
"open",
|
|
20058
|
+
"closed",
|
|
20059
|
+
"unknown",
|
|
20060
|
+
"not-opening"
|
|
20061
|
+
]);
|
|
20062
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20063
|
+
var NcAlarmSensorStateSchema = object({
|
|
20064
|
+
deviceId: number().int().positive(),
|
|
20065
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20066
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20067
|
+
state: string().nullable(),
|
|
20068
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20069
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20070
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20071
|
+
online: boolean().nullable()
|
|
20072
|
+
});
|
|
20073
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20074
|
+
var NcAlarmSensorsSchema = object({
|
|
20075
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20076
|
+
readAt: number().int().nonnegative()
|
|
20077
|
+
});
|
|
20029
20078
|
/**
|
|
20030
20079
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20031
20080
|
*
|
|
@@ -20116,7 +20165,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20116
20165
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20117
20166
|
kind: "mutation",
|
|
20118
20167
|
auth: "admin"
|
|
20119
|
-
});
|
|
20168
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20120
20169
|
/**
|
|
20121
20170
|
* Zod schemas for persisted record types.
|
|
20122
20171
|
*
|
|
@@ -20463,12 +20512,26 @@ var CameraSensorRefSchema = object({
|
|
|
20463
20512
|
function cameraSensorRefKey(ref) {
|
|
20464
20513
|
return `${ref.addonId}/${ref.stableId}`;
|
|
20465
20514
|
}
|
|
20466
|
-
/**
|
|
20467
|
-
|
|
20468
|
-
|
|
20469
|
-
|
|
20470
|
-
|
|
20471
|
-
|
|
20515
|
+
/**
|
|
20516
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
20517
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
20518
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
20519
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
20520
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
20521
|
+
*/
|
|
20522
|
+
var CameraSensorModeSchema = _enum([
|
|
20523
|
+
"in-addition",
|
|
20524
|
+
"confirm",
|
|
20525
|
+
"replace"
|
|
20526
|
+
]);
|
|
20527
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
20528
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
20529
|
+
/**
|
|
20530
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
20531
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
20532
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
20533
|
+
*/
|
|
20534
|
+
var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
|
|
20472
20535
|
const seen = /* @__PURE__ */ new Set();
|
|
20473
20536
|
value.sensors.forEach((ref, index) => {
|
|
20474
20537
|
const key = cameraSensorRefKey(ref);
|
|
@@ -20480,39 +20543,41 @@ var CameraSensorsConfigSchema = object({
|
|
|
20480
20543
|
seen.add(key);
|
|
20481
20544
|
});
|
|
20482
20545
|
});
|
|
20483
|
-
|
|
20546
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
20547
|
+
var AttachmentFields = {
|
|
20484
20548
|
addonId: string(),
|
|
20485
|
-
stableId: string()
|
|
20549
|
+
stableId: string(),
|
|
20550
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
20486
20551
|
};
|
|
20487
20552
|
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
20488
20553
|
object({
|
|
20489
|
-
...
|
|
20554
|
+
...AttachmentFields,
|
|
20490
20555
|
state: literal("ready"),
|
|
20491
20556
|
deviceId: number(),
|
|
20492
20557
|
name: string(),
|
|
20493
20558
|
caps: array(string()).readonly()
|
|
20494
20559
|
}),
|
|
20495
20560
|
object({
|
|
20496
|
-
...
|
|
20561
|
+
...AttachmentFields,
|
|
20497
20562
|
state: literal("offline"),
|
|
20498
20563
|
deviceId: number(),
|
|
20499
20564
|
name: string(),
|
|
20500
20565
|
reason: _enum(["offline", "disabled"])
|
|
20501
20566
|
}),
|
|
20502
20567
|
object({
|
|
20503
|
-
...
|
|
20568
|
+
...AttachmentFields,
|
|
20504
20569
|
state: literal("missing"),
|
|
20505
20570
|
reason: string()
|
|
20506
20571
|
}),
|
|
20507
20572
|
object({
|
|
20508
|
-
...
|
|
20573
|
+
...AttachmentFields,
|
|
20509
20574
|
state: literal("unsupported"),
|
|
20510
20575
|
deviceId: number(),
|
|
20511
20576
|
name: string(),
|
|
20512
20577
|
reason: string()
|
|
20513
20578
|
}),
|
|
20514
20579
|
object({
|
|
20515
|
-
...
|
|
20580
|
+
...AttachmentFields,
|
|
20516
20581
|
state: literal("unreadable"),
|
|
20517
20582
|
reason: string()
|
|
20518
20583
|
})
|
|
@@ -20525,17 +20590,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
|
20525
20590
|
* say.
|
|
20526
20591
|
*/
|
|
20527
20592
|
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
20593
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
20594
|
+
var CameraOwnMotionSchema = _enum([
|
|
20595
|
+
"always",
|
|
20596
|
+
"when-confirmed",
|
|
20597
|
+
"never"
|
|
20598
|
+
]);
|
|
20599
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
20600
|
+
var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
|
|
20601
|
+
/**
|
|
20602
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
20603
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
20604
|
+
* so a view of the camera's own row reads this.
|
|
20605
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
20606
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
20607
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
20608
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
20609
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
20610
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
20611
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
20612
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
20613
|
+
*/
|
|
20614
|
+
var CameraRawLevelSchema = object({
|
|
20615
|
+
detected: boolean(),
|
|
20616
|
+
atMs: number()
|
|
20617
|
+
});
|
|
20528
20618
|
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
20529
|
-
object({
|
|
20619
|
+
object({
|
|
20620
|
+
state: literal("not-configured"),
|
|
20621
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20622
|
+
}),
|
|
20530
20623
|
object({
|
|
20531
20624
|
state: literal("unreadable"),
|
|
20532
|
-
reason: string()
|
|
20625
|
+
reason: string(),
|
|
20626
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20533
20627
|
}),
|
|
20534
20628
|
object({
|
|
20535
20629
|
state: literal("configured"),
|
|
20536
|
-
|
|
20630
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
20537
20631
|
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
20538
|
-
|
|
20632
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
20633
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
20634
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
20635
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
20539
20636
|
})
|
|
20540
20637
|
]);
|
|
20541
20638
|
Object.freeze({
|
|
@@ -23726,8 +23823,10 @@ var RunnerCameraConfigSchema = object({
|
|
|
23726
23823
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
23727
23824
|
* analyzer providers) running on decoded frames in this runner.
|
|
23728
23825
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
23729
|
-
* analytics). The provider emits ProviderMotion
|
|
23730
|
-
*
|
|
23826
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
23827
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
23828
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
23829
|
+
* `reportMotion`.
|
|
23731
23830
|
*/
|
|
23732
23831
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
23733
23832
|
/**
|
|
@@ -23904,7 +24003,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
23904
24003
|
hasGpu: boolean(),
|
|
23905
24004
|
inferenceBackend: string().optional(),
|
|
23906
24005
|
cpuCores: number().optional()
|
|
23907
|
-
})
|
|
24006
|
+
}),
|
|
24007
|
+
/**
|
|
24008
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
24009
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
24010
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
24011
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
24012
|
+
* writers.
|
|
24013
|
+
*/
|
|
24014
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
23908
24015
|
});
|
|
23909
24016
|
/**
|
|
23910
24017
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -28745,6 +28852,17 @@ object({
|
|
|
28745
28852
|
deviceId: number(),
|
|
28746
28853
|
status: DeviceStatusSchema
|
|
28747
28854
|
});
|
|
28855
|
+
object({
|
|
28856
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
28857
|
+
lastPressedAt: number().nullable(),
|
|
28858
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
28859
|
+
pressCountSinceStart: number()
|
|
28860
|
+
});
|
|
28861
|
+
object({
|
|
28862
|
+
deviceId: number(),
|
|
28863
|
+
timestamp: number()
|
|
28864
|
+
});
|
|
28865
|
+
DeviceType.Button, DeviceType.Camera;
|
|
28748
28866
|
/**
|
|
28749
28867
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
28750
28868
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -30389,9 +30507,9 @@ object({
|
|
|
30389
30507
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
30390
30508
|
lastDetectedAt: number().nullable(),
|
|
30391
30509
|
/**
|
|
30392
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
30393
|
-
* `null` while false and on every `Sensor`
|
|
30394
|
-
* constant's doc for the one-authority rule.
|
|
30510
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
30511
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
30512
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
30395
30513
|
*
|
|
30396
30514
|
* ## Reading this field still arms nothing
|
|
30397
30515
|
*
|
|
@@ -30409,38 +30527,41 @@ object({
|
|
|
30409
30527
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
30410
30528
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
30411
30529
|
*
|
|
30412
|
-
* ## Who writes it
|
|
30413
|
-
*
|
|
30414
|
-
* - **Cameras** — the
|
|
30415
|
-
*
|
|
30416
|
-
* `
|
|
30417
|
-
* `
|
|
30418
|
-
*
|
|
30419
|
-
*
|
|
30420
|
-
* a
|
|
30421
|
-
*
|
|
30422
|
-
*
|
|
30423
|
-
*
|
|
30424
|
-
*
|
|
30425
|
-
*
|
|
30426
|
-
*
|
|
30427
|
-
*
|
|
30428
|
-
*
|
|
30429
|
-
*
|
|
30430
|
-
* `
|
|
30431
|
-
*
|
|
30432
|
-
*
|
|
30433
|
-
*
|
|
30434
|
-
*
|
|
30435
|
-
*
|
|
30436
|
-
*
|
|
30437
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
30438
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
30439
|
-
* "sole writer" wording without also removing the other writers.
|
|
30530
|
+
* ## Who writes it (D696)
|
|
30531
|
+
*
|
|
30532
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
30533
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
30534
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
30535
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
30536
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
30537
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
30538
|
+
* that never sends a clear falls one window after its last `true`.
|
|
30539
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
30540
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
30541
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
30542
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
30543
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
30544
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
30545
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
30546
|
+
* system's own state change. That is the sensor's own fact.
|
|
30547
|
+
*
|
|
30548
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
30549
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
30550
|
+
*
|
|
30551
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
30552
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
30553
|
+
* it, every provider seeded it at boot, and every session left it
|
|
30554
|
+
* `detected: true` after its detach.
|
|
30440
30555
|
*/
|
|
30441
30556
|
autoClearAfterMs: number().nullable()
|
|
30442
30557
|
});
|
|
30443
|
-
|
|
30558
|
+
/**
|
|
30559
|
+
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
30560
|
+
* event `EventCategory.MotionOnMotionChanged`. Single source of truth
|
|
30561
|
+
* — both the cap event surface and the bus payload type alias to this
|
|
30562
|
+
* schema.
|
|
30563
|
+
*/
|
|
30564
|
+
var MotionOnMotionChangedDataSchema = object({
|
|
30444
30565
|
deviceId: number(),
|
|
30445
30566
|
detected: boolean(),
|
|
30446
30567
|
timestamp: number(),
|
|
@@ -40499,6 +40620,12 @@ Object.freeze({
|
|
|
40499
40620
|
addonId: null,
|
|
40500
40621
|
access: "view"
|
|
40501
40622
|
},
|
|
40623
|
+
"notificationRules.getAlarmSensors": {
|
|
40624
|
+
capName: "notification-rules",
|
|
40625
|
+
capScope: "system",
|
|
40626
|
+
addonId: null,
|
|
40627
|
+
access: "view"
|
|
40628
|
+
},
|
|
40502
40629
|
"notificationRules.getClipRetentionAsks": {
|
|
40503
40630
|
capName: "notification-rules",
|
|
40504
40631
|
capScope: "system",
|
|
@@ -44982,6 +45109,11 @@ Object.freeze({
|
|
|
44982
45109
|
form: "single",
|
|
44983
45110
|
optional: false
|
|
44984
45111
|
}],
|
|
45112
|
+
"notificationRules.getAlarmSensors": [{
|
|
45113
|
+
name: "deviceIds",
|
|
45114
|
+
form: "array",
|
|
45115
|
+
optional: false
|
|
45116
|
+
}],
|
|
44985
45117
|
"notificationRules.setDeviceMuted": [{
|
|
44986
45118
|
name: "deviceId",
|
|
44987
45119
|
form: "single",
|
|
@@ -46917,6 +47049,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
46917
47049
|
createdAt: number(),
|
|
46918
47050
|
updatedAt: number()
|
|
46919
47051
|
});
|
|
47052
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
46920
47053
|
object({
|
|
46921
47054
|
/**
|
|
46922
47055
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -47118,7 +47251,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
47118
47251
|
capability: adminUiCapability,
|
|
47119
47252
|
provider: {
|
|
47120
47253
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
47121
|
-
getVersion: async () => ({ version: "1.2.
|
|
47254
|
+
getVersion: async () => ({ version: "1.2.300" })
|
|
47122
47255
|
}
|
|
47123
47256
|
}];
|
|
47124
47257
|
}
|