@camstack/addon-pipeline-orchestrator 1.2.324 → 1.2.325
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/_stub.js +509 -359
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-C-txzh2m.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-DUstnfGf.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-6CTaeZSL.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-s9I9eY7F.mjs +26 -0
- package/dist/{hostInit-C689lJpv.mjs → hostInit-DMNJfKN-.mjs} +3 -3
- package/dist/index.js +266 -78
- package/dist/index.mjs +266 -78
- package/dist/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CdOR1t-0.mjs +0 -26
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-iNnhcbuC.mjs +0 -26
package/dist/index.mjs
CHANGED
|
@@ -5390,7 +5390,7 @@ var ZodIssueCode = {
|
|
|
5390
5390
|
var ZodFirstPartyTypeKind;
|
|
5391
5391
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5392
5392
|
//#endregion
|
|
5393
|
-
//#region ../types/dist/sleep-
|
|
5393
|
+
//#region ../types/dist/sleep-DRqxtc0C.mjs
|
|
5394
5394
|
/**
|
|
5395
5395
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5396
5396
|
* window to float samples (D455).
|
|
@@ -8730,6 +8730,10 @@ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(o
|
|
|
8730
8730
|
kind: "mutation",
|
|
8731
8731
|
auth: "admin"
|
|
8732
8732
|
}), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
|
|
8733
|
+
object({
|
|
8734
|
+
code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
|
|
8735
|
+
params: record(string(), union([string(), number()])).optional()
|
|
8736
|
+
});
|
|
8733
8737
|
/**
|
|
8734
8738
|
* Promise-based timer helpers — used everywhere the codebase needs to
|
|
8735
8739
|
* wait, back off, or schedule a retry. Before these helpers landed, each
|
|
@@ -8755,7 +8759,7 @@ function sleep(ms) {
|
|
|
8755
8759
|
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
8756
8760
|
}
|
|
8757
8761
|
//#endregion
|
|
8758
|
-
//#region ../types/dist/err-msg-
|
|
8762
|
+
//#region ../types/dist/err-msg-DLerKiVO.mjs
|
|
8759
8763
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
8760
8764
|
DeviceType["Camera"] = "camera";
|
|
8761
8765
|
DeviceType["Hub"] = "hub";
|
|
@@ -9005,6 +9009,22 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
9005
9009
|
DeviceRole["Nightvision"] = "nightvision";
|
|
9006
9010
|
DeviceRole["PrivacyMask"] = "privacy-mask";
|
|
9007
9011
|
DeviceRole["Doorbell"] = "doorbell";
|
|
9012
|
+
/** Interior blind / shade / roller blind. HA `device_class: blind|shade`. */
|
|
9013
|
+
DeviceRole["CoverBlind"] = "cover-blind";
|
|
9014
|
+
/** Exterior roller shutter. HA `device_class: shutter`; Homematic BROLL. */
|
|
9015
|
+
DeviceRole["CoverShutter"] = "cover-shutter";
|
|
9016
|
+
/** Exterior awning. HA `device_class: awning`. */
|
|
9017
|
+
DeviceRole["CoverAwning"] = "cover-awning";
|
|
9018
|
+
/** Curtain / drape. HA `device_class: curtain`. */
|
|
9019
|
+
DeviceRole["CoverCurtain"] = "cover-curtain";
|
|
9020
|
+
/** Garage door. HA `device_class: garage`. A security actuator: exports gate it. */
|
|
9021
|
+
DeviceRole["CoverGarage"] = "cover-garage";
|
|
9022
|
+
/** Gate. HA `device_class: gate`. A security actuator: exports gate it. */
|
|
9023
|
+
DeviceRole["CoverGate"] = "cover-gate";
|
|
9024
|
+
/** Door. HA `device_class: door`. A security actuator: exports gate it. */
|
|
9025
|
+
DeviceRole["CoverDoor"] = "cover-door";
|
|
9026
|
+
/** Window. HA `device_class: window`. */
|
|
9027
|
+
DeviceRole["CoverWindow"] = "cover-window";
|
|
9008
9028
|
/** Virtual HA toggle (input_boolean.*) — distinguishable from a
|
|
9009
9029
|
* real Switch device for UI rendering / export adapters. */
|
|
9010
9030
|
DeviceRole["BinaryHelper"] = "binary-helper";
|
|
@@ -9085,7 +9105,7 @@ function errMsg$2(err) {
|
|
|
9085
9105
|
return String(err);
|
|
9086
9106
|
}
|
|
9087
9107
|
//#endregion
|
|
9088
|
-
//#region ../types/dist/composition-
|
|
9108
|
+
//#region ../types/dist/composition-EQ9Ok0Ee.mjs
|
|
9089
9109
|
/**
|
|
9090
9110
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
9091
9111
|
*
|
|
@@ -13223,7 +13243,8 @@ var ConvertResultSchema = object({
|
|
|
13223
13243
|
})).readonly()
|
|
13224
13244
|
});
|
|
13225
13245
|
_enum(["new-session", "step-up"]);
|
|
13226
|
-
|
|
13246
|
+
/** The languages the hub's app landing pages are written in (D858). */
|
|
13247
|
+
var AppPageLangSchema = _enum(["en", "it"]);
|
|
13227
13248
|
/** How a native app starts one login method (D858), as `auth.listLoginMethods` reports it. */
|
|
13228
13249
|
var AppLoginPathSchema = discriminatedUnion("kind", [object({ kind: literal("native") }), object({
|
|
13229
13250
|
kind: literal("browser"),
|
|
@@ -13720,7 +13741,9 @@ var ConfigTabDeclarationSchema = object({
|
|
|
13720
13741
|
var ConfigSectionWithValuesSchema = object({
|
|
13721
13742
|
id: string(),
|
|
13722
13743
|
title: string(),
|
|
13744
|
+
titleKey: string().optional(),
|
|
13723
13745
|
description: string().optional(),
|
|
13746
|
+
descriptionKey: string().optional(),
|
|
13724
13747
|
style: _enum(["card", "accordion"]).optional(),
|
|
13725
13748
|
defaultCollapsed: boolean().optional(),
|
|
13726
13749
|
columns: union([
|
|
@@ -17003,6 +17026,9 @@ method(object({
|
|
|
17003
17026
|
}), method(object({ refs: RefListSchema }), KeychainResolveResultSchema, { auth: "admin" }), method(object({ refs: RefListSchema }), object({ deleted: number().int() }), {
|
|
17004
17027
|
kind: "mutation",
|
|
17005
17028
|
auth: "admin"
|
|
17029
|
+
}), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
|
|
17030
|
+
kind: "mutation",
|
|
17031
|
+
auth: "admin"
|
|
17006
17032
|
}), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
|
|
17007
17033
|
/**
|
|
17008
17034
|
* device-history — the ONE mechanism for numeric history (D850).
|
|
@@ -38406,6 +38432,38 @@ var DeviceRegisterPayloadSchema = object({
|
|
|
38406
38432
|
* omits it and the keyword backstop applies. */
|
|
38407
38433
|
secretConfigPaths: array(string()).optional()
|
|
38408
38434
|
});
|
|
38435
|
+
/** One deleted device, kept by device-manager so an addon that missed the
|
|
38436
|
+
* deletion can still learn of it (D865). Written by the delete path ONLY. */
|
|
38437
|
+
var DeviceTombstoneSchema = object({
|
|
38438
|
+
deviceId: number().int().positive(),
|
|
38439
|
+
/** Epoch ms the device was deleted. */
|
|
38440
|
+
deletedAt: number(),
|
|
38441
|
+
/** The addon that owned the device when it was deleted. */
|
|
38442
|
+
providerAddonId: string()
|
|
38443
|
+
});
|
|
38444
|
+
/** Data held for one device that device-manager no longer knows. */
|
|
38445
|
+
var OrphanDeviceDataSchema = object({
|
|
38446
|
+
deviceId: number().int().positive(),
|
|
38447
|
+
/** Rows/files per store (`<addonId>:<store>`). */
|
|
38448
|
+
stores: record(string(), number().int().nonnegative())
|
|
38449
|
+
});
|
|
38450
|
+
var CleanupDeletedDevicesResultSchema = object({
|
|
38451
|
+
/**
|
|
38452
|
+
* `skipped` — the absence check could not be trusted (a device-list read
|
|
38453
|
+
* failed or the two reads disagreed); nothing was listed or deleted.
|
|
38454
|
+
* `dry-run` — `devices` is what a confirmed run would delete.
|
|
38455
|
+
* `cleaned` — `devices` is what was deleted.
|
|
38456
|
+
*/
|
|
38457
|
+
status: _enum([
|
|
38458
|
+
"skipped",
|
|
38459
|
+
"dry-run",
|
|
38460
|
+
"cleaned"
|
|
38461
|
+
]),
|
|
38462
|
+
reason: string().nullable(),
|
|
38463
|
+
devices: array(OrphanDeviceDataSchema),
|
|
38464
|
+
/** Implementers that could not be asked (their stores are not in `devices`). */
|
|
38465
|
+
unreachable: array(string())
|
|
38466
|
+
});
|
|
38409
38467
|
var DeviceRemovePayloadSchema = object({ deviceId: number() });
|
|
38410
38468
|
var DevicePersistConfigPayloadSchema = object({
|
|
38411
38469
|
deviceId: number(),
|
|
@@ -38644,6 +38702,9 @@ method(object({
|
|
|
38644
38702
|
}), method(object({ deviceId: number() }), object({ success: literal(true) }), {
|
|
38645
38703
|
kind: "mutation",
|
|
38646
38704
|
auth: "admin"
|
|
38705
|
+
}), method(object({ sinceMs: number() }), array(DeviceTombstoneSchema).readonly(), { auth: "admin" }), method(object({ confirm: boolean() }), CleanupDeletedDevicesResultSchema, {
|
|
38706
|
+
kind: "mutation",
|
|
38707
|
+
auth: "admin"
|
|
38647
38708
|
}), method(object({ integrationId: string() }), object({ removed: number() }), {
|
|
38648
38709
|
kind: "mutation",
|
|
38649
38710
|
auth: "admin"
|
|
@@ -39106,6 +39167,72 @@ method(object({
|
|
|
39106
39167
|
auth: "admin"
|
|
39107
39168
|
});
|
|
39108
39169
|
/**
|
|
39170
|
+
* `device-removal-hook` — the reliable way an addon learns a device was DELETED,
|
|
39171
|
+
* so it can delete what it keeps for that device (D865).
|
|
39172
|
+
*
|
|
39173
|
+
* ## Why an event was not enough
|
|
39174
|
+
*
|
|
39175
|
+
* `DeviceUnregistered` is telemetry and may be dropped (D8, D11). An addon that
|
|
39176
|
+
* hung its per-device clean-up on it left durable garbage whenever the event was
|
|
39177
|
+
* lost, the addon was down, or it was restarting at that moment — footage,
|
|
39178
|
+
* analytics rows and settings of device 4483 outlived the device. Loss of this
|
|
39179
|
+
* signal corrupts durable state, so it travels by RPC with a recorded fact
|
|
39180
|
+
* behind it (D8: "if loss would corrupt durable state, use RPC plus a reconcile").
|
|
39181
|
+
*
|
|
39182
|
+
* ## The three pieces
|
|
39183
|
+
*
|
|
39184
|
+
* 1. device-manager records a TOMBSTONE per deleted device
|
|
39185
|
+
* (`deviceManager.listDeletedSince`). The tombstone is written by the delete
|
|
39186
|
+
* path only — a device that is unregistered, offline or whose provider is
|
|
39187
|
+
* restarting is NOT deleted and gets none.
|
|
39188
|
+
* 2. After a delete, device-manager calls `onDeviceRemoved` on EVERY provider of
|
|
39189
|
+
* this collection, one by one, with bounded retries, logged.
|
|
39190
|
+
* 3. An implementer that was down asks `deviceManager.listDeletedSince` at start
|
|
39191
|
+
* (and periodically) and runs its own `onDeviceRemoved` for each tombstone it
|
|
39192
|
+
* may have missed. Reconcile is driven by tombstones, never by "the device is
|
|
39193
|
+
* not in the current list": a failed or partial list read must not destroy data.
|
|
39194
|
+
*
|
|
39195
|
+
* ## Contract for an implementer
|
|
39196
|
+
*
|
|
39197
|
+
* - **Idempotent.** It is called again by a retry, by a reconcile and by the
|
|
39198
|
+
* admin cleanup of data that predates tombstones. A device with nothing left
|
|
39199
|
+
* answers zero counts.
|
|
39200
|
+
* - **One key per store** in `counts`, deleted rows/files per store, so the log
|
|
39201
|
+
* line and the admin dry run can say where the data was.
|
|
39202
|
+
* - **Training datasets are NOT device data** and are never deleted by a hook.
|
|
39203
|
+
* - **Per-device SETTINGS are not hooked.** Configuration lives in the standard
|
|
39204
|
+
* per-device store (`ctx.settings.*DeviceStore`), which device-manager clears
|
|
39205
|
+
* for every addon centrally at delete time. This hook is for device DATA
|
|
39206
|
+
* that is not settings: footage, event media, analytics rows, history.
|
|
39207
|
+
* - A provider that cannot tell is allowed to throw; the caller retries it.
|
|
39208
|
+
*
|
|
39209
|
+
* `listDeviceData` is the read side of the admin "Clean data of deleted devices"
|
|
39210
|
+
* action: which device ids this addon holds data for, and how much per store. It
|
|
39211
|
+
* never deletes. device-manager decides which of those ids are absent from the
|
|
39212
|
+
* fleet, from TWO consistent reads of the device list (D49).
|
|
39213
|
+
*/
|
|
39214
|
+
/** What a hook is told about the deletion. */
|
|
39215
|
+
var DeviceRemovedInputSchema = object({
|
|
39216
|
+
deviceId: number().int().positive(),
|
|
39217
|
+
/** Epoch ms the device was deleted (the tombstone's `deletedAt`). */
|
|
39218
|
+
deletedAt: number(),
|
|
39219
|
+
/** The addon that owned the device, as device-manager last knew it. */
|
|
39220
|
+
providerAddonId: string()
|
|
39221
|
+
});
|
|
39222
|
+
/** Rows/files/refs deleted, per store this implementer owns. */
|
|
39223
|
+
var DeviceRemovedResultSchema = object({ counts: record(string(), number().int().nonnegative()) });
|
|
39224
|
+
/** One (store, device) pair an implementer holds data for. */
|
|
39225
|
+
var DeviceDataEntrySchema = object({
|
|
39226
|
+
store: string(),
|
|
39227
|
+
deviceId: number().int().positive(),
|
|
39228
|
+
/** Rows (or files) held for the device in the store. */
|
|
39229
|
+
count: number().int().nonnegative()
|
|
39230
|
+
});
|
|
39231
|
+
method(DeviceRemovedInputSchema, DeviceRemovedResultSchema, {
|
|
39232
|
+
kind: "mutation",
|
|
39233
|
+
auth: "admin"
|
|
39234
|
+
}), method(_void(), array(DeviceDataEntrySchema).readonly(), { auth: "admin" });
|
|
39235
|
+
/**
|
|
39109
39236
|
* `failure-contribution` — the capability an addon reports its OWN losses
|
|
39110
39237
|
* through, per camera, with the denominator attached. It stores nothing.
|
|
39111
39238
|
*
|
|
@@ -64674,6 +64801,12 @@ Object.freeze({
|
|
|
64674
64801
|
addonId: null,
|
|
64675
64802
|
access: "create"
|
|
64676
64803
|
},
|
|
64804
|
+
"deviceManager.cleanupDeletedDevicesData": {
|
|
64805
|
+
capName: "device-manager",
|
|
64806
|
+
capScope: "system",
|
|
64807
|
+
addonId: null,
|
|
64808
|
+
access: "create"
|
|
64809
|
+
},
|
|
64677
64810
|
"deviceManager.createDevice": {
|
|
64678
64811
|
capName: "device-manager",
|
|
64679
64812
|
capScope: "system",
|
|
@@ -64854,6 +64987,12 @@ Object.freeze({
|
|
|
64854
64987
|
addonId: null,
|
|
64855
64988
|
access: "view"
|
|
64856
64989
|
},
|
|
64990
|
+
"deviceManager.listDeletedSince": {
|
|
64991
|
+
capName: "device-manager",
|
|
64992
|
+
capScope: "system",
|
|
64993
|
+
addonId: null,
|
|
64994
|
+
access: "view"
|
|
64995
|
+
},
|
|
64857
64996
|
"deviceManager.listDeviceIdsByCaps": {
|
|
64858
64997
|
capName: "device-manager",
|
|
64859
64998
|
capScope: "system",
|
|
@@ -65262,6 +65401,18 @@ Object.freeze({
|
|
|
65262
65401
|
addonId: null,
|
|
65263
65402
|
access: "create"
|
|
65264
65403
|
},
|
|
65404
|
+
"deviceRemovalHook.listDeviceData": {
|
|
65405
|
+
capName: "device-removal-hook",
|
|
65406
|
+
capScope: "system",
|
|
65407
|
+
addonId: null,
|
|
65408
|
+
access: "view"
|
|
65409
|
+
},
|
|
65410
|
+
"deviceRemovalHook.onDeviceRemoved": {
|
|
65411
|
+
capName: "device-removal-hook",
|
|
65412
|
+
capScope: "system",
|
|
65413
|
+
addonId: null,
|
|
65414
|
+
access: "create"
|
|
65415
|
+
},
|
|
65265
65416
|
"deviceState.claimFields": {
|
|
65266
65417
|
capName: "device-state",
|
|
65267
65418
|
capScope: "system",
|
|
@@ -65694,6 +65845,12 @@ Object.freeze({
|
|
|
65694
65845
|
addonId: null,
|
|
65695
65846
|
access: "delete"
|
|
65696
65847
|
},
|
|
65848
|
+
"keychain.deleteDeviceScope": {
|
|
65849
|
+
capName: "keychain",
|
|
65850
|
+
capScope: "system",
|
|
65851
|
+
addonId: null,
|
|
65852
|
+
access: "delete"
|
|
65853
|
+
},
|
|
65697
65854
|
"keychain.getState": {
|
|
65698
65855
|
capName: "keychain",
|
|
65699
65856
|
capScope: "system",
|
|
@@ -71734,6 +71891,11 @@ Object.freeze({
|
|
|
71734
71891
|
form: "single",
|
|
71735
71892
|
optional: false
|
|
71736
71893
|
}],
|
|
71894
|
+
"deviceRemovalHook.onDeviceRemoved": [{
|
|
71895
|
+
name: "deviceId",
|
|
71896
|
+
form: "single",
|
|
71897
|
+
optional: false
|
|
71898
|
+
}],
|
|
71737
71899
|
"deviceState.claimFields": [{
|
|
71738
71900
|
name: "deviceId",
|
|
71739
71901
|
form: "single",
|
|
@@ -71923,6 +72085,11 @@ Object.freeze({
|
|
|
71923
72085
|
form: "single",
|
|
71924
72086
|
optional: false
|
|
71925
72087
|
}],
|
|
72088
|
+
"keychain.deleteDeviceScope": [{
|
|
72089
|
+
name: "deviceId",
|
|
72090
|
+
form: "single",
|
|
72091
|
+
optional: false
|
|
72092
|
+
}],
|
|
71926
72093
|
"lawnMowerControl.dock": [{
|
|
71927
72094
|
name: "deviceId",
|
|
71928
72095
|
form: "single",
|
|
@@ -74271,6 +74438,8 @@ new Set([
|
|
|
74271
74438
|
"audio-tools",
|
|
74272
74439
|
"audio-silence"
|
|
74273
74440
|
]);
|
|
74441
|
+
AppPageLangSchema.options;
|
|
74442
|
+
record(string().min(1), string());
|
|
74274
74443
|
/**
|
|
74275
74444
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
74276
74445
|
*
|
|
@@ -75972,6 +76141,25 @@ var DETAIL_CROP_PADDING_FIELD = {
|
|
|
75972
76141
|
default: DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio
|
|
75973
76142
|
};
|
|
75974
76143
|
/**
|
|
76144
|
+
* The cadence of the automatic whole-archive face rescore (D866).
|
|
76145
|
+
*
|
|
76146
|
+
* One cluster-wide knob in `pipeline-orchestrator`'s GLOBAL settings, read by
|
|
76147
|
+
* `pipeline-analytics` over the hub-routed `addon-settings` cap on every tick.
|
|
76148
|
+
* It lives here for the same reason the detail-crop convention does: the
|
|
76149
|
+
* writer (orchestrator) and the reader (analytics) are different addons, they
|
|
76150
|
+
* never import each other, and a key copied by hand is how a setting silently
|
|
76151
|
+
* stops arriving.
|
|
76152
|
+
*/
|
|
76153
|
+
var FACE_RESCORE_SECTION_ID = "face-rescore";
|
|
76154
|
+
var FACE_RESCORE_INTERVAL_KEY = "faceRescoreIntervalMinutes";
|
|
76155
|
+
/** Slider bounds. `0` is "disabled"; anything in 1..9 is raised to `min`. */
|
|
76156
|
+
var FACE_RESCORE_INTERVAL_FIELD = {
|
|
76157
|
+
min: 0,
|
|
76158
|
+
max: 1440,
|
|
76159
|
+
step: 5,
|
|
76160
|
+
default: 60
|
|
76161
|
+
};
|
|
76162
|
+
/**
|
|
75975
76163
|
* THE native-frame **lease** knobs — hold depth, RAM budget, demand window and
|
|
75976
76164
|
* subject-tile budget for the decode worker's native-resolution retention.
|
|
75977
76165
|
*
|
|
@@ -83735,67 +83923,20 @@ function buildRunnerConfig(base, overrides) {
|
|
|
83735
83923
|
preRollInferenceFrames: config.preRollInferenceFrames
|
|
83736
83924
|
};
|
|
83737
83925
|
}
|
|
83738
|
-
|
|
83739
|
-
|
|
83740
|
-
|
|
83741
|
-
|
|
83742
|
-
name: "deviceId",
|
|
83743
|
-
type: "TEXT",
|
|
83744
|
-
primaryKey: true,
|
|
83745
|
-
notNull: true
|
|
83746
|
-
},
|
|
83747
|
-
(
|
|
83748
|
-
/** The feature name list, verbatim. */
|
|
83749
|
-
{
|
|
83750
|
-
name: "features",
|
|
83751
|
-
type: "JSON",
|
|
83752
|
-
notNull: true
|
|
83753
|
-
}),
|
|
83754
|
-
{
|
|
83755
|
-
name: "updatedAt",
|
|
83756
|
-
type: "INTEGER",
|
|
83757
|
-
notNull: true
|
|
83758
|
-
}
|
|
83759
|
-
],
|
|
83760
|
-
writeMode: "write-behind",
|
|
83761
|
-
keyOf: (row) => String(row.deviceId),
|
|
83762
|
-
toValue: (row) => ({
|
|
83763
|
-
features: [...row.features],
|
|
83764
|
-
updatedAt: row.updatedAt
|
|
83765
|
-
}),
|
|
83766
|
-
fromRecord: (key, data) => {
|
|
83767
|
-
const deviceId = Number(key);
|
|
83768
|
-
const raw = data["features"];
|
|
83769
|
-
if (!Number.isFinite(deviceId) || !Array.isArray(raw)) return null;
|
|
83770
|
-
const features = raw.filter((f) => typeof f === "string");
|
|
83771
|
-
if (features.length === 0) return null;
|
|
83772
|
-
const updatedAt = Number(data["updatedAt"]);
|
|
83773
|
-
return {
|
|
83774
|
-
deviceId,
|
|
83775
|
-
features,
|
|
83776
|
-
updatedAt: Number.isFinite(updatedAt) ? updatedAt : 0,
|
|
83777
|
-
restored: true
|
|
83778
|
-
};
|
|
83779
|
-
},
|
|
83780
|
-
deviceIdOf: (row) => row.deviceId
|
|
83781
|
-
};
|
|
83926
|
+
//#endregion
|
|
83927
|
+
//#region src/device-features-mirror.ts
|
|
83928
|
+
/** The per-device settings key a device's mirrored features live under. */
|
|
83929
|
+
var DEVICE_FEATURES_KEY = "deviceFeatures";
|
|
83782
83930
|
var DeviceFeaturesMirror = class {
|
|
83783
83931
|
/** Process-local fallback, used only when no store was supplied. */
|
|
83784
83932
|
local = /* @__PURE__ */ new Map();
|
|
83785
|
-
|
|
83933
|
+
settings;
|
|
83786
83934
|
logger;
|
|
83787
83935
|
now;
|
|
83788
83936
|
constructor(deps) {
|
|
83789
83937
|
this.logger = deps.logger;
|
|
83790
83938
|
this.now = deps.now ?? (() => Date.now());
|
|
83791
|
-
this.
|
|
83792
|
-
spec: DEVICE_FEATURES_SPEC,
|
|
83793
|
-
store: deps.store,
|
|
83794
|
-
logger: deps.logger
|
|
83795
|
-
});
|
|
83796
|
-
}
|
|
83797
|
-
static declare(store) {
|
|
83798
|
-
return DurableLedger.declare(store, DEVICE_FEATURES_SPEC);
|
|
83939
|
+
this.settings = deps.settings ?? null;
|
|
83799
83940
|
}
|
|
83800
83941
|
/**
|
|
83801
83942
|
* Seed the mirror from the last session. Call once at boot, after `declare`
|
|
@@ -83803,13 +83944,29 @@ var DeviceFeaturesMirror = class {
|
|
|
83803
83944
|
* already there when the first read fails.
|
|
83804
83945
|
*/
|
|
83805
83946
|
async hydrate() {
|
|
83806
|
-
|
|
83807
|
-
|
|
83808
|
-
|
|
83809
|
-
|
|
83947
|
+
const settings = this.settings;
|
|
83948
|
+
if (settings === null) return 0;
|
|
83949
|
+
const list = settings.listDeviceStoreIds;
|
|
83950
|
+
if (list !== void 0) {
|
|
83951
|
+
const ids = await list.call(settings);
|
|
83952
|
+
const batch = settings.readDeviceStoreBatch;
|
|
83953
|
+
const blobs = batch === void 0 ? new Map(await Promise.all(ids.map(async (id) => [id, await settings.readDeviceStore(id)]))) : await batch.call(settings, ids);
|
|
83954
|
+
for (const [deviceId, blob] of blobs) {
|
|
83955
|
+
const row = rowOf(deviceId, blob[DEVICE_FEATURES_KEY]);
|
|
83956
|
+
if (row !== null) this.local.set(deviceId, row);
|
|
83957
|
+
}
|
|
83958
|
+
}
|
|
83959
|
+
this.logger.info("device-features mirror restored", { meta: { devices: this.local.size } });
|
|
83960
|
+
return this.local.size;
|
|
83810
83961
|
}
|
|
83811
83962
|
held(deviceId) {
|
|
83812
|
-
return this.
|
|
83963
|
+
return this.local.get(deviceId);
|
|
83964
|
+
}
|
|
83965
|
+
async persist(deviceId, features, updatedAt) {
|
|
83966
|
+
await this.settings?.writeDeviceStore(deviceId, { [DEVICE_FEATURES_KEY]: {
|
|
83967
|
+
features: [...features],
|
|
83968
|
+
updatedAt
|
|
83969
|
+
} });
|
|
83813
83970
|
}
|
|
83814
83971
|
remember(deviceId, features) {
|
|
83815
83972
|
const row = {
|
|
@@ -83818,20 +83975,19 @@ var DeviceFeaturesMirror = class {
|
|
|
83818
83975
|
updatedAt: this.now(),
|
|
83819
83976
|
restored: false
|
|
83820
83977
|
};
|
|
83821
|
-
|
|
83822
|
-
|
|
83823
|
-
return;
|
|
83824
|
-
}
|
|
83825
|
-
const held = this.durable.get(String(deviceId));
|
|
83978
|
+
const held = this.local.get(deviceId);
|
|
83979
|
+
this.local.set(deviceId, row);
|
|
83826
83980
|
if (held !== void 0 && !held.restored && sameFeatures(held.features, features)) return;
|
|
83827
|
-
this.
|
|
83981
|
+
this.persist(deviceId, features, row.updatedAt).catch((err) => {
|
|
83982
|
+
this.logger.warn("device-features mirror not persisted", {
|
|
83983
|
+
tags: { deviceId },
|
|
83984
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
83985
|
+
});
|
|
83986
|
+
});
|
|
83828
83987
|
}
|
|
83829
83988
|
drop(deviceId) {
|
|
83830
|
-
|
|
83831
|
-
|
|
83832
|
-
return;
|
|
83833
|
-
}
|
|
83834
|
-
this.durable.forget(String(deviceId));
|
|
83989
|
+
this.local.delete(deviceId);
|
|
83990
|
+
this.settings?.writeDeviceStore(deviceId, { [DEVICE_FEATURES_KEY]: void 0 });
|
|
83835
83991
|
}
|
|
83836
83992
|
/**
|
|
83837
83993
|
* Resolve a device's features, preferring a fresh read but never letting a
|
|
@@ -83880,7 +84036,7 @@ var DeviceFeaturesMirror = class {
|
|
|
83880
84036
|
this.drop(deviceId);
|
|
83881
84037
|
return [];
|
|
83882
84038
|
}
|
|
83883
|
-
/** Drop a device's mirror
|
|
84039
|
+
/** Drop a device's mirror. (A removed device's settings are cleared centrally, D865.) */
|
|
83884
84040
|
forget(deviceId) {
|
|
83885
84041
|
this.drop(deviceId);
|
|
83886
84042
|
}
|
|
@@ -83891,6 +84047,20 @@ function sameFeatures(a, b) {
|
|
|
83891
84047
|
const held = new Set(a);
|
|
83892
84048
|
return b.every((f) => held.has(f));
|
|
83893
84049
|
}
|
|
84050
|
+
function rowOf(deviceId, raw) {
|
|
84051
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
84052
|
+
const features = Reflect.get(raw, "features");
|
|
84053
|
+
if (!Array.isArray(features)) return null;
|
|
84054
|
+
const kept = features.filter((f) => typeof f === "string");
|
|
84055
|
+
if (kept.length === 0) return null;
|
|
84056
|
+
const updatedAt = Number(Reflect.get(raw, "updatedAt"));
|
|
84057
|
+
return {
|
|
84058
|
+
deviceId,
|
|
84059
|
+
features: kept,
|
|
84060
|
+
updatedAt: Number.isFinite(updatedAt) ? updatedAt : 0,
|
|
84061
|
+
restored: true
|
|
84062
|
+
};
|
|
84063
|
+
}
|
|
83894
84064
|
//#endregion
|
|
83895
84065
|
//#region src/onboard-forwarding-reconcile.ts
|
|
83896
84066
|
/** The `detectionSources` member that means "this camera's own firmware". */
|
|
@@ -84049,9 +84219,10 @@ var DetectionWiringController = class {
|
|
|
84049
84219
|
featuresMirror;
|
|
84050
84220
|
constructor(deps) {
|
|
84051
84221
|
this.deps = deps;
|
|
84222
|
+
const settings = deps.persistFeatures === true ? deps.ctx().settings : void 0;
|
|
84052
84223
|
this.featuresMirror = new DeviceFeaturesMirror({
|
|
84053
84224
|
logger: deps.logger,
|
|
84054
|
-
...
|
|
84225
|
+
...settings !== void 0 ? { settings } : {}
|
|
84055
84226
|
});
|
|
84056
84227
|
}
|
|
84057
84228
|
/**
|
|
@@ -84060,8 +84231,7 @@ var DetectionWiringController = class {
|
|
|
84060
84231
|
* that would have needed it.
|
|
84061
84232
|
*/
|
|
84062
84233
|
async hydrateFeaturesMirror() {
|
|
84063
|
-
if (this.deps.
|
|
84064
|
-
await DeviceFeaturesMirror.declare(this.deps.featuresStore);
|
|
84234
|
+
if (this.deps.persistFeatures !== true) return;
|
|
84065
84235
|
await this.featuresMirror.hydrate();
|
|
84066
84236
|
}
|
|
84067
84237
|
/** `activeDetections.get(deviceId)`. */
|
|
@@ -94359,7 +94529,7 @@ async function buildOrchestratorControllers(deps) {
|
|
|
94359
94529
|
reconcile.scheduleReconcile();
|
|
94360
94530
|
const detectionWiring = new DetectionWiringController({
|
|
94361
94531
|
ctx: () => deps.ctx(),
|
|
94362
|
-
|
|
94532
|
+
persistFeatures: true,
|
|
94363
94533
|
ledger,
|
|
94364
94534
|
placement,
|
|
94365
94535
|
audio,
|
|
@@ -94579,6 +94749,24 @@ function buildGlobalSettingsSections(options) {
|
|
|
94579
94749
|
default: DEFAULT_DETAIL_CROP_CONVENTION.square
|
|
94580
94750
|
}]
|
|
94581
94751
|
},
|
|
94752
|
+
{
|
|
94753
|
+
id: FACE_RESCORE_SECTION_ID,
|
|
94754
|
+
title: "Face suggestions",
|
|
94755
|
+
tab: "pipeline",
|
|
94756
|
+
description: "How often the people suggestions on unassigned faces are refreshed against the current gallery. The job only runs when the gallery or the set of unassigned faces changed since the last run; otherwise it does nothing.",
|
|
94757
|
+
fields: [{
|
|
94758
|
+
key: FACE_RESCORE_INTERVAL_KEY,
|
|
94759
|
+
type: "slider",
|
|
94760
|
+
label: "Suggestion refresh interval",
|
|
94761
|
+
description: "0 = off (use the Recompute suggestions button). Values from 1 to 9 run every 10 minutes. The first run happens one interval after the addon starts.",
|
|
94762
|
+
min: FACE_RESCORE_INTERVAL_FIELD.min,
|
|
94763
|
+
max: FACE_RESCORE_INTERVAL_FIELD.max,
|
|
94764
|
+
step: FACE_RESCORE_INTERVAL_FIELD.step,
|
|
94765
|
+
default: FACE_RESCORE_INTERVAL_FIELD.default,
|
|
94766
|
+
showValue: true,
|
|
94767
|
+
unit: "min"
|
|
94768
|
+
}]
|
|
94769
|
+
},
|
|
94582
94770
|
{
|
|
94583
94771
|
id: NATIVE_LEASE_SECTION_ID,
|
|
94584
94772
|
title: "Native frame lease",
|
package/dist/remoteEntry.js
CHANGED
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-DUstnfGf.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline-orchestrator",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.325",
|
|
4
4
|
"description": "Hub-side camera-to-agent load balancer — tracks runner capacity and dispatches attachCamera calls to the optimal pipeline-runner instance",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|