@camstack/addon-admin-ui 1.2.271 → 1.2.272

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.
Files changed (81) hide show
  1. package/dist/assets/{AddonCollectionPage-DqzCMX3d.js → AddonCollectionPage-D6fy7dpj.js} +1 -1
  2. package/dist/assets/{Addons-Cfzhy1FL.js → Addons-BsQHKMWG.js} +1 -1
  3. package/dist/assets/{AdminTabs-k3mRubjE.js → AdminTabs-V9k1QuVP.js} +1 -1
  4. package/dist/assets/{AiProfiles-CYFmuxOf.js → AiProfiles-DiPkD_fk.js} +1 -1
  5. package/dist/assets/{BrokerForm-CIY1d1d7.js → BrokerForm-CYGBfbxr.js} +1 -1
  6. package/dist/assets/{Build-IIy-q7uD.js → Build-CBeEDpy5.js} +3 -3
  7. package/dist/assets/{Capabilities-Bn8ZC2CW.js → Capabilities-D1KT-ivA.js} +1 -1
  8. package/dist/assets/{CapabilityBadges-DldALMee.js → CapabilityBadges-DS8SoWoz.js} +1 -1
  9. package/dist/assets/{Cluster-B8FyeYha.js → Cluster-gJW9vP03.js} +1 -1
  10. package/dist/assets/{Data-dNt8Y-C9.js → Data-Bh0bzESu.js} +1 -1
  11. package/dist/assets/{DetectionIntelligence-wp6N_etF.js → DetectionIntelligence-Cv2fg-SI.js} +1 -1
  12. package/dist/assets/{DeviceAggregateSection-CU1nQkPf.js → DeviceAggregateSection-DHALwPAJ.js} +1 -1
  13. package/dist/assets/{DeviceDetail-DKhrYv1V.js → DeviceDetail-Cj4upIZ8.js} +2 -2
  14. package/dist/assets/{Devices-DlqwzcD1.js → Devices-HDneMnHi.js} +1 -1
  15. package/dist/assets/{EmbedPlayerPage-DU6hDBqg.js → EmbedPlayerPage-B_wGVEK0.js} +1 -1
  16. package/dist/assets/{Events-CjI9E2hP.js → Events-BPXFJIla.js} +1 -1
  17. package/dist/assets/{FormBuilder-Dc6E_voV.js → FormBuilder-BXtojpHF.js} +1 -1
  18. package/dist/assets/{Identity-0lewBgT-.js → Identity-_IPjFsQw.js} +1 -1
  19. package/dist/assets/{IntegrationDetail-YdhQQL83.js → IntegrationDetail-DIY7Jywc.js} +1 -1
  20. package/dist/assets/{Integrations-CdDCtOkK.js → Integrations-DXOrcEGt.js} +1 -1
  21. package/dist/assets/{Integrations-yaU-gfjg.js → Integrations-mJpIsz9F.js} +1 -1
  22. package/dist/assets/{Locations-BfO7yEPX.js → Locations-wB0U93K4.js} +2 -2
  23. package/dist/assets/{Logs-DUYk0c3A.js → Logs-BYTo71Yt.js} +1 -1
  24. package/dist/assets/{MotionZonesSettings-BckmPRiR.js → MotionZonesSettings-DDf16JDF.js} +1 -1
  25. package/dist/assets/{MyAccess-BFQMx9o3.js → MyAccess-BbWITi4N.js} +1 -1
  26. package/dist/assets/{Network-CIk-9jzK.js → Network-30R4cY39.js} +1 -1
  27. package/dist/assets/{NodeAddonsSettingsPanel-DJrBrOZU.js → NodeAddonsSettingsPanel-UySNHnGf.js} +1 -1
  28. package/dist/assets/{NodeInferenceDevices-4ReR6_7N.js → NodeInferenceDevices-B3VEAQWr.js} +1 -1
  29. package/dist/assets/Notifications-C1yukm6c.js +1 -0
  30. package/dist/assets/Pipeline-DXl1Hzdu.js +1 -0
  31. package/dist/assets/{Plates-B4prub48.js → Plates-BIhVH_IZ.js} +1 -1
  32. package/dist/assets/{PrivacyMaskSettings-Cv5zA9gQ.js → PrivacyMaskSettings-C0HZcbXR.js} +1 -1
  33. package/dist/assets/{ProviderIcon-DCfQzHIr.js → ProviderIcon-DXK0cuQe.js} +1 -1
  34. package/dist/assets/{Recordings-bZJhzJsd.js → Recordings-CfpOjuow.js} +1 -1
  35. package/dist/assets/{ScanNetworkModal-gzNZ-LAb.js → ScanNetworkModal-B3CQ1S3f.js} +1 -1
  36. package/dist/assets/{SceneMonitorEditor-pno9hqpn.js → SceneMonitorEditor-BN7kLz08.js} +1 -1
  37. package/dist/assets/{Scenes-DtKIr9F_.js → Scenes-Dbko4G3U.js} +1 -1
  38. package/dist/assets/{Settings-BCPiq_88.js → Settings-eB6bRRQ2.js} +1 -1
  39. package/dist/assets/{Showroom-IZoJF2xo.js → Showroom-D7VNR9sm.js} +1 -1
  40. package/dist/assets/{StorageLocationsPanel-BSKjMvak.js → StorageLocationsPanel-CfOU5MKV.js} +1 -1
  41. package/dist/assets/{Terminal-4EjaVPEr.js → Terminal-DJ13Ptlg.js} +1 -1
  42. package/dist/assets/{Viewer-DpLmscaq.js → Viewer-DSNI0gBQ.js} +1 -1
  43. package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BtKTkhyx.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-CHnD_XCi.js} +1 -1
  44. package/dist/assets/{archive-BB3ec_n-.js → archive-CfPc3zmd.js} +1 -1
  45. package/dist/assets/{authed-media-Bqv01DZY.js → authed-media-D0FYWdWm.js} +1 -1
  46. package/dist/assets/{boxes-BxaSpZkk.js → boxes-Bziwj8sB.js} +1 -1
  47. package/dist/assets/circle-slash-DNDn3yid.js +1 -0
  48. package/dist/assets/{debounced-invalidate-CAdmny96.js → debounced-invalidate-Bpjoo47a.js} +1 -1
  49. package/dist/assets/dist-CRVdBpiI.js +349 -0
  50. package/dist/assets/{dist-C8vQbt24.js → dist-CnCHhuKr.js} +1 -1
  51. package/dist/assets/{face-bbox-CfSqm4Yv.js → face-bbox-CTW2Ql-L.js} +1 -1
  52. package/dist/assets/{hard-drive-download-BQnyHdfx.js → hard-drive-download-D69_02_z.js} +1 -1
  53. package/dist/assets/{hostInit-D6CdLzdb.js → hostInit-Duev9E28.js} +1 -1
  54. package/dist/assets/{index-BKWONarY.js → index-BjhxGD-m.js} +3 -3
  55. package/dist/assets/{layers-BCrYpCnW.js → layers-dj0W-5PD.js} +1 -1
  56. package/dist/assets/{location-owned-usage-CSpMCCbU.js → location-owned-usage-Dd31wc7R.js} +1 -1
  57. package/dist/assets/{mf-entry-bootstrap-0-a15f07ff.js → mf-entry-bootstrap-0-f2ee65db.js} +2 -2
  58. package/dist/assets/{player-overlays-CZvLgyNg.js → player-overlays-BCwjKg6p.js} +1 -1
  59. package/dist/assets/remoteEntry-DUHRclu_.js +1 -0
  60. package/dist/assets/{send-C3IG3eJW.js → send-DI8RyAAG.js} +1 -1
  61. package/dist/assets/{settings-2-BnPcSjOh.js → settings-2-pQ157vcG.js} +1 -1
  62. package/dist/assets/{square-check-big-CPDPjmHM.js → square-check-big-CluVAeV_.js} +1 -1
  63. package/dist/assets/{src-BZTmBMCp.js → src-BI1z_AYO.js} +7 -7
  64. package/dist/assets/src-D2MUU060.js +349 -0
  65. package/dist/assets/{use-scenes-feed-D1KpjfQY.js → use-scenes-feed-Do31SA2K.js} +1 -1
  66. package/dist/assets/{use-stationary-objects-DyHqCMnC.js → use-stationary-objects-DqcSiA8T.js} +1 -1
  67. package/dist/assets/useEventInvalidation-GeG-PeIJ.js +1 -0
  68. package/dist/assets/{useNodeUrlSelection-BUzugSCi.js → useNodeUrlSelection-BsR42Cfa.js} +1 -1
  69. package/dist/assets/user-round-DG8UupM9.js +1 -0
  70. package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-C0cIlp9L.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-CwUNfWUA.js} +2 -2
  71. package/dist/index.html +5 -5
  72. package/dist/server/addon.js +1084 -728
  73. package/package.json +1 -1
  74. package/dist/assets/Notifications-DzKNUl7R.js +0 -1
  75. package/dist/assets/Pipeline-ai7qzobB.js +0 -1
  76. package/dist/assets/circle-slash-C8eiZoEi.js +0 -1
  77. package/dist/assets/dist-E283Fu6V.js +0 -349
  78. package/dist/assets/remoteEntry-C_uTdAWt.js +0 -1
  79. package/dist/assets/src-CIZ3ediW.js +0 -349
  80. package/dist/assets/useEventInvalidation-BBv2U92f.js +0 -1
  81. package/dist/assets/user-round-DYOT4vMb.js +0 -1
@@ -5361,7 +5361,7 @@ var ZodIssueCode = {
5361
5361
  var ZodFirstPartyTypeKind;
5362
5362
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5363
5363
  //#endregion
5364
- //#region ../types/dist/sleep-DU7mu4wb.mjs
5364
+ //#region ../types/dist/sleep-BaRu0bS5.mjs
5365
5365
  /**
5366
5366
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5367
5367
  * window to float samples (D455).
@@ -9434,7 +9434,7 @@ var ModelFormatEntrySchema = object({
9434
9434
  /** Multi-file payload (directory members or sibling files). */
9435
9435
  files: array(string()).readonly().optional(),
9436
9436
  /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
9437
- runtimes: array(_enum(["node", "python"])).readonly().optional()
9437
+ runtimes: array(_enum(["python"])).readonly().optional()
9438
9438
  });
9439
9439
  /**
9440
9440
  * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
@@ -17046,6 +17046,29 @@ var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
17046
17046
  ]);
17047
17047
  NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
17048
17048
  /**
17049
+ * The panel's transitions, as ONE list.
17050
+ *
17051
+ * Named here rather than spelled out at each of the four sites that need them
17052
+ * (the emitter, the intake, the editor group, the combined-notification gate),
17053
+ * because a transition added to the enum and forgotten at one of them is an
17054
+ * alarm state nobody can be notified about. That is exactly what this list
17055
+ * failed to prevent while it held three: `alarm-arming` was the fourth.
17056
+ *
17057
+ * In LIFECYCLE order, which is the order an editor lists them in and the order
17058
+ * a person experiences them — not the order they were added.
17059
+ */
17060
+ var NC_ALARM_SYSTEM_EVENT_KINDS = [
17061
+ "alarm-arm-refused",
17062
+ "alarm-check-failed",
17063
+ "alarm-arming",
17064
+ "alarm-armed",
17065
+ "alarm-pending",
17066
+ "alarm-triggered",
17067
+ "alarm-rearmed",
17068
+ "alarm-sensor-bypass",
17069
+ "alarm-disarmed"
17070
+ ];
17071
+ /**
17049
17072
  * One coherent system-event condition. `kinds` is the required opt-in safety
17050
17073
  * gate; the remaining lists are optional narrowing filters relevant to the
17051
17074
  * selected kinds.
@@ -17112,6 +17135,25 @@ var NcScheduleSchema = object({
17112
17135
  /** Active OUTSIDE the windows (e.g. "only outside business hours"). */
17113
17136
  invert: boolean().optional()
17114
17137
  });
17138
+ /**
17139
+ * How a system-event rule of the `device-events` or `system` family speaks
17140
+ * (D647): at once, per event (`instant`, the only behaviour before D647), or
17141
+ * as a STATE SUMMARY at the end of each window of `schedule`.
17142
+ */
17143
+ var NcSystemEventDeliveryModeSchema = _enum(["instant", "summary"]);
17144
+ /**
17145
+ * `summary`: the rule sends NOTHING per event. When a window of `schedule`
17146
+ * CLOSES, it sends one notification with the current state of its kinds
17147
+ * (low batteries, consumables to replace, devices offline, updates
17148
+ * available, ...), after its own filters. Nothing to report sends nothing.
17149
+ * The schedule is the ordinary `NcSchedule` (weekly windows, IANA timezone,
17150
+ * midnight crossing); the send time is each window's END. Refused on the
17151
+ * `alarm` family, which stays instant (`systemEventDeliveryProblems`).
17152
+ */
17153
+ var NcSystemEventDeliverySchema = discriminatedUnion("mode", [object({ mode: literal("instant") }), object({
17154
+ mode: literal("summary"),
17155
+ schedule: NcScheduleSchema
17156
+ })]);
17115
17157
  /** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
17116
17158
  var NcPlateMatcherSchema = object({
17117
17159
  /**
@@ -17847,6 +17889,16 @@ var NcRuleInputSchema = object({
17847
17889
  delivery: NcDeliverySchema,
17848
17890
  conditions: NcConditionsSchema.default({}),
17849
17891
  schedule: NcScheduleSchema.optional(),
17892
+ /**
17893
+ * A `device-events` / `system` rule's delivery (D647): absent or `instant`
17894
+ * is a notification per event; `summary` is one state summary per closed
17895
+ * window of its schedule. `.optional()` and never defaulted: absent must
17896
+ * keep meaning what every rule authored before D647 meant, with no
17897
+ * migration. Top-level rather than inside `conditions.systemEvent`, so a
17898
+ * client that does not know it (an older viewer re-sending `conditions`
17899
+ * whole) leaves it standing through the store's patch merge.
17900
+ */
17901
+ systemEventDelivery: NcSystemEventDeliverySchema.optional(),
17850
17902
  /** May be empty when `targetUsers` addresses at least one user — the
17851
17903
  * "at least one addressee" invariant is enforced by the provider, because
17852
17904
  * a cross-field refine here would break `NcRulePatchSchema.partial()`. */
@@ -18075,6 +18127,28 @@ var NcRuleSchema = NcRuleInputSchema.extend({
18075
18127
  */
18076
18128
  disabledTargetIds: array(string()).default([])
18077
18129
  });
18130
+ /** One section of a previewed state summary. `unavailable` = its state could not be read. */
18131
+ var NcStateSummaryPreviewSectionSchema = object({
18132
+ id: string(),
18133
+ status: _enum(["read", "unavailable"]),
18134
+ items: number().int().nonnegative(),
18135
+ reason: string().optional()
18136
+ });
18137
+ /**
18138
+ * The summary a rule would send now. `empty` = nothing to report and every
18139
+ * section read: such a summary is NOT sent. `dropped` counts the open states
18140
+ * the rule's own filters (or a camera mute) left out, by reason.
18141
+ * `excludedGroups` names the kind groups selected that have no state to report
18142
+ * (backups & exports).
18143
+ */
18144
+ var NcStateSummaryPreviewSchema = object({
18145
+ empty: boolean(),
18146
+ count: number().int().nonnegative(),
18147
+ text: string(),
18148
+ sections: array(NcStateSummaryPreviewSectionSchema),
18149
+ dropped: record(string(), number().int().nonnegative()),
18150
+ excludedGroups: array(string())
18151
+ });
18078
18152
  var NcTestResultSchema = object({
18079
18153
  recordId: string(),
18080
18154
  recordKind: _enum([
@@ -18166,6 +18240,13 @@ var NcTemplateVarDescriptorSchema = object({
18166
18240
  kinds: array(NcTemplateVarKindSchema).optional(),
18167
18241
  deliveries: array(NcDeliverySchema).optional(),
18168
18242
  systemEventKinds: array(NcSystemEventKindSchema).optional(),
18243
+ /**
18244
+ * Which system-event DELIVERY has a value for it (D647). Absent = an
18245
+ * instant row only when the descriptor names `systemEventKinds` (a
18246
+ * per-event fact: a summary row has no single device), and both otherwise.
18247
+ * `['summary']` marks the state-summary vocabulary (`{{summaryText}}`, ...).
18248
+ */
18249
+ systemEventDeliveries: array(NcSystemEventDeliveryModeSchema).optional(),
18169
18250
  dynamic: object({
18170
18251
  prefix: literal("count_"),
18171
18252
  from: literal("classes")
@@ -18178,7 +18259,9 @@ var NcTemplatePreviewInputSchema = object({
18178
18259
  field: NcTemplateFieldSchema,
18179
18260
  kind: NcRuleKindSchema.optional(),
18180
18261
  delivery: NcDeliverySchema.optional(),
18181
- systemEventKinds: array(NcSystemEventKindSchema).optional()
18262
+ systemEventKinds: array(NcSystemEventKindSchema).optional(),
18263
+ /** The rule's system-event delivery (D647); absent = instant. */
18264
+ systemEventDelivery: NcSystemEventDeliveryModeSchema.optional()
18182
18265
  }),
18183
18266
  template: object({
18184
18267
  title: string().max(500).optional(),
@@ -18712,6 +18795,10 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
18712
18795
  }), object({ results: array(NcTestResultSchema) }), {
18713
18796
  kind: "mutation",
18714
18797
  auth: "admin"
18798
+ }), method(object({ rule: NcRuleInputSchema }), NcStateSummaryPreviewSchema, {
18799
+ kind: "mutation",
18800
+ auth: "admin",
18801
+ access: "view"
18715
18802
  }), method(object({}), object({
18716
18803
  catalog: array(NcConditionDescriptorSchema),
18717
18804
  taxonomy: NcTaxonomySchema.optional()
@@ -19058,606 +19145,6 @@ var OauthIntegrationDescriptorSchema = object({
19058
19145
  });
19059
19146
  method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
19060
19147
  /**
19061
- * Reference to the frame's retained NATIVE surface + the parent crop's placement
19062
- * within the frame, so the executor can re-cut a leaf child ROI at native
19063
- * resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
19064
- */
19065
- var NativeCropRefSchema = object({
19066
- /** Handle keying the retained native surface (node-pinned to its owner). */
19067
- handle: FrameHandleSchema,
19068
- /** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
19069
- cropFrameSpace: object({
19070
- x: number(),
19071
- y: number(),
19072
- w: number(),
19073
- h: number()
19074
- })
19075
- });
19076
- object({
19077
- crop: object({
19078
- left: number(),
19079
- top: number(),
19080
- width: number().positive(),
19081
- height: number().positive()
19082
- }).optional(),
19083
- content: object({
19084
- width: number().int().positive(),
19085
- height: number().int().positive()
19086
- }),
19087
- fit: _enum(["stretch", "contain"]),
19088
- format: _enum([
19089
- "rgb",
19090
- "gray",
19091
- "jpeg"
19092
- ])
19093
- });
19094
- /**
19095
- * Process-local frame identity. It is serializable so it can ride an in-process
19096
- * capability call, but `registryId` deliberately prevents resolution in any
19097
- * other process or execution group.
19098
- */
19099
- var FrameRefSchema = object({
19100
- registryId: string().min(1),
19101
- id: string().min(1),
19102
- width: number().int().positive(),
19103
- height: number().int().positive(),
19104
- format: _enum(["rgb", "gray"]),
19105
- timestamp: number(),
19106
- capturedAt: number().optional()
19107
- });
19108
- var ModelFormatSchema$1 = _enum([
19109
- "onnx",
19110
- "coreml",
19111
- "openvino",
19112
- "tflite",
19113
- "pt",
19114
- "gguf"
19115
- ]);
19116
- var PipelineSlotSchema = _enum([
19117
- "detector",
19118
- "cropper",
19119
- "classifier",
19120
- "refiner",
19121
- "audio-classifier"
19122
- ]);
19123
- var PipelineEngineChoiceSchema = object({
19124
- runtime: _enum(["node", "python"]),
19125
- backend: string(),
19126
- format: ModelFormatSchema$1,
19127
- device: string().optional()
19128
- });
19129
- var AvailableEngineSchema = object({
19130
- engine: PipelineEngineChoiceSchema,
19131
- devices: array(object({
19132
- id: string(),
19133
- label: string(),
19134
- description: string().optional()
19135
- })).readonly(),
19136
- defaultDevice: string()
19137
- });
19138
- var PipelineDefaultStepSchema = lazy(() => object({
19139
- addonId: string(),
19140
- addonName: string(),
19141
- slot: PipelineSlotSchema,
19142
- inputClasses: array(string()).readonly(),
19143
- outputClasses: array(string()).readonly(),
19144
- enabled: boolean(),
19145
- modelId: string(),
19146
- children: array(PipelineDefaultStepSchema).readonly(),
19147
- group: string().optional(),
19148
- settings: record(string(), unknown()).optional()
19149
- }));
19150
- var PipelineTemplateStepSchema = lazy(() => object({
19151
- addonId: string(),
19152
- enabled: boolean(),
19153
- modelId: string(),
19154
- children: array(PipelineTemplateStepSchema).readonly(),
19155
- settings: record(string(), unknown()).optional()
19156
- }));
19157
- var PipelineTemplateSchema$1 = object({
19158
- id: string(),
19159
- name: string(),
19160
- createdAt: string(),
19161
- updatedAt: string(),
19162
- engine: PipelineEngineChoiceSchema,
19163
- steps: array(PipelineTemplateStepSchema).readonly()
19164
- });
19165
- var PipelineModelOptionSchema = object({
19166
- id: string(),
19167
- name: string(),
19168
- formats: record(string(), object({
19169
- downloaded: boolean(),
19170
- sizeMB: number()
19171
- })),
19172
- group: ModelVariantGroupSchema.optional(),
19173
- legacy: boolean().optional(),
19174
- provider: ModelProviderIdSchema.optional()
19175
- });
19176
- var ConfigFieldBridge = custom();
19177
- var PipelineAddonSchemaSchema = object({
19178
- id: string(),
19179
- name: string(),
19180
- slot: PipelineSlotSchema,
19181
- inputClasses: array(string()).readonly(),
19182
- outputClasses: array(string()).readonly(),
19183
- childSlots: array(PipelineSlotSchema).readonly(),
19184
- models: array(PipelineModelOptionSchema).readonly(),
19185
- defaultModelId: string(),
19186
- defaultModelIdByFormat: record(string(), string()).optional(),
19187
- enabledByDefault: boolean().optional(),
19188
- backfillIntoExistingOverrides: boolean().optional(),
19189
- defaultConfidence: number(),
19190
- group: string().optional(),
19191
- configSchema: array(ConfigFieldBridge).readonly().optional()
19192
- });
19193
- var PipelineSlotSchemaSchema = object({
19194
- id: PipelineSlotSchema,
19195
- label: string(),
19196
- priority: number(),
19197
- parentSlot: PipelineSlotSchema.nullable(),
19198
- addons: array(PipelineAddonSchemaSchema).readonly()
19199
- });
19200
- var PipelineSchemaSchema = object({
19201
- availableEngines: array(AvailableEngineSchema).readonly(),
19202
- selectedEngine: PipelineEngineChoiceSchema,
19203
- slots: array(PipelineSlotSchemaSchema).readonly()
19204
- });
19205
- var EngineProvisioningSchema = object({
19206
- runtimeId: _enum([
19207
- "onnx",
19208
- "openvino",
19209
- "coreml",
19210
- "edgetpu"
19211
- ]).nullable(),
19212
- device: string().nullable(),
19213
- state: _enum([
19214
- "idle",
19215
- "installing",
19216
- "verifying",
19217
- "ready",
19218
- "failed"
19219
- ]),
19220
- progress: number().optional(),
19221
- error: string().optional(),
19222
- nextRetryAt: number().optional(),
19223
- /**
19224
- * Gate A (config-correctness gate at engine change): human-readable
19225
- * config issues surfaced EAGERLY when the node's engine changes — model
19226
- * substitutions ("chose X, running Y") and zero-build steps ("no model
19227
- * has a <format> build"). Additive/optional: informational only, never
19228
- * enforced here — `assertEngineReady` (readiness) still gates inference.
19229
- * Absent/empty when the node-default tree resolves cleanly.
19230
- */
19231
- configIssues: array(string()).optional()
19232
- });
19233
- var PipelineStepInputSchema = lazy(() => object({
19234
- addonId: string(),
19235
- modelId: string().optional(),
19236
- enabled: boolean().default(true),
19237
- children: array(PipelineStepInputSchema).optional(),
19238
- settings: record(string(), unknown()).optional(),
19239
- jumpDeviceKey: string().optional()
19240
- }));
19241
- var ModelSubstitutionSchema = object({
19242
- addonId: string(),
19243
- chosen: string(),
19244
- running: string(),
19245
- format: string()
19246
- });
19247
- var PipelineValidationIssueSchema = object({
19248
- addonId: string(),
19249
- kind: _enum(["unknown-addon", "no-format-build"]),
19250
- detail: string()
19251
- });
19252
- var PipelineValidationResultSchema = object({
19253
- ok: boolean(),
19254
- issues: array(PipelineValidationIssueSchema).readonly(),
19255
- substitutions: array(ModelSubstitutionSchema).readonly(),
19256
- /** The node's `currentEngine.format` this validation ran against. */
19257
- format: string()
19258
- });
19259
- var ReferenceImageEntrySchema = object({
19260
- filename: string(),
19261
- stepIds: array(string()).readonly().optional()
19262
- });
19263
- var ReferenceImageBodySchema = object({
19264
- base64: string(),
19265
- filename: string()
19266
- });
19267
- var ReferenceAudioEntrySchema = object({
19268
- filename: string(),
19269
- sizeKb: number()
19270
- });
19271
- var ReferenceAudioBodySchema = object({ base64: string() });
19272
- var AudioBackendSchema = object({
19273
- id: string(),
19274
- name: string(),
19275
- description: string(),
19276
- available: boolean(),
19277
- /**
19278
- * Raw classifier labels this backend can emit (e.g. YAMNet's
19279
- * 521-class set or Apple SoundAnalysis's 303-class set). Used by
19280
- * the benchmark UI to populate the `enabledMicroClasses` filter
19281
- * specific to the selected backend without a separate fetch.
19282
- */
19283
- rawLabels: array(string()).readonly().optional()
19284
- });
19285
- var AudioCapabilitiesSchema = object({
19286
- activeBackend: string(),
19287
- availableBackends: array(AudioBackendSchema).readonly(),
19288
- sampleRate: number(),
19289
- chunkDurationMs: number()
19290
- });
19291
- var DownloadModelResultSchema = object({
19292
- filePath: string(),
19293
- sizeMB: number(),
19294
- durationMs: number()
19295
- });
19296
- /**
19297
- * Wrapper carrying a single test run's result. Replaces the legacy
19298
- * ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
19299
- * canonical `AudioResult` from the Phase 6 output rework: one
19300
- * `AudioDetection` per class above `minScore`, top-N candidates in
19301
- * `debug.alternateLabels['audio-classifier']`, per-source timings in
19302
- * `debug.stepTimings`. The outer `success`/`error` fields stay so the
19303
- * benchmark UI can still report a clean failure when the classifier
19304
- * cap isn't available.
19305
- */
19306
- var AudioTestResultSchema = object({
19307
- success: boolean(),
19308
- error: string().optional(),
19309
- frame: custom().optional()
19310
- });
19311
- var PipelineConfigBridge = custom();
19312
- var ConfigUISchemaBridge = custom();
19313
- var ConfigUISchemaNullableBridge = custom();
19314
- var InferenceCapabilitiesBridge = custom();
19315
- var ModelAvailabilityListBridge = custom();
19316
- var PipelineRunResultBridge = custom();
19317
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
19318
- modelId: string(),
19319
- settings: record(string(), unknown()).readonly()
19320
- }))), method(object({ steps: record(string(), object({
19321
- modelId: string(),
19322
- settings: record(string(), unknown()).readonly()
19323
- })) }), object({ success: literal(true) }), {
19324
- kind: "mutation",
19325
- auth: "admin"
19326
- }), method(object({ nodeId: string() }), object({
19327
- success: literal(true),
19328
- clearedDevices: number()
19329
- }), {
19330
- kind: "mutation",
19331
- auth: "admin"
19332
- }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
19333
- /** `<backend>:<device>`, e.g. `openvino:gpu`. */
19334
- deviceKey: string(),
19335
- /**
19336
- * `failed` — the per-device restart budget is exhausted; no pool
19337
- * will be spawned until an operator re-arms it or the runner
19338
- * respawns. `backoff` — under budget, waiting out the backoff (or
19339
- * a cached pool observed dead and not yet condemned).
19340
- */
19341
- state: _enum(["failed", "backoff"]),
19342
- /** Epoch ms of the death that produced this state. */
19343
- since: number(),
19344
- /** Pool deaths inside the current window. */
19345
- deaths: number(),
19346
- /** The last death's message. */
19347
- lastError: string()
19348
- })).readonly() })), method(object({
19349
- nodeId: string(),
19350
- deviceKey: string()
19351
- }), object({ rearmed: boolean() }), {
19352
- kind: "mutation",
19353
- auth: "admin"
19354
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({ steps: array(PipelineStepInputSchema) }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
19355
- name: string(),
19356
- steps: array(PipelineTemplateStepSchema).readonly(),
19357
- engine: PipelineEngineChoiceSchema
19358
- }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
19359
- id: string(),
19360
- name: string().optional(),
19361
- steps: array(PipelineTemplateStepSchema).readonly().optional()
19362
- }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
19363
- addonId: string(),
19364
- modelId: string(),
19365
- format: ModelFormatSchema$1
19366
- }), DownloadModelResultSchema, { kind: "mutation" }), method(object({
19367
- addonId: string(),
19368
- modelId: string(),
19369
- format: ModelFormatSchema$1
19370
- }), object({ success: literal(true) }), { kind: "mutation" }), method(object({
19371
- engine: PipelineEngineChoiceSchema.optional(),
19372
- steps: array(PipelineStepInputSchema).min(1),
19373
- frame: FrameInputSchema.optional(),
19374
- /**
19375
- * Process-local lazy frame. Valid only when caller and provider resolve
19376
- * in the same execution-group process; split/cross-node callers use
19377
- * `frame`/`image` inline compatibility instead.
19378
- */
19379
- frameRef: FrameRefSchema.optional(),
19380
- /**
19381
- * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
19382
- * the decoded pixels live in. One more member of the one-of
19383
- * frame/frameHandle/image/imageBase64/referenceImage group.
19384
- */
19385
- frameHandle: FrameHandleSchema.optional(),
19386
- imageBase64: string().optional(),
19387
- /**
19388
- * Binary JPEG bytes — preferred over `imageBase64` on internal
19389
- * hops (hub → forked worker via Moleculer MsgPack) because it
19390
- * skips the 33% base64 overhead + the per-call base64 decode on
19391
- * the detection-pipeline worker. Callers can pass either; exactly
19392
- * one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
19393
- */
19394
- image: _instanceof(Uint8Array).optional(),
19395
- referenceImage: string().optional(),
19396
- deviceId: number().optional(),
19397
- sessionId: string().optional(),
19398
- /**
19399
- * Execution plane. 'full' (default) runs the whole tree — benchmark,
19400
- * reference-image, and detail-subtree calls. 'frame' is the live
19401
- * per-frame dispatch: ONLY root-plane steps run; crop children
19402
- * (inputClasses ≠ null) are skipped and served per-track via
19403
- * pipelineRunner.runDetailSubtree (two-plane design).
19404
- */
19405
- plane: _enum(["full", "frame"]).optional(),
19406
- /**
19407
- * Inference-device selector (Phase 2 multi-device). Format
19408
- * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
19409
- * Omitted ⇒ the runner's default device (current single-engine
19410
- * behaviour). Selects WHICH device pool of the node runs the call.
19411
- */
19412
- deviceKey: string().optional(),
19413
- /**
19414
- * Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
19415
- * when the parent crop was resolved from the frame's retained NATIVE
19416
- * surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
19417
- * child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
19418
- * resolution from that surface — the SAME quality path faces already
19419
- * had — instead of the downscaled parent tile. `handle` keys the native
19420
- * surface (node-pinned to its owner); `cropFrameSpace` is the parent
19421
- * crop's padded/clamped rectangle in FRAME-space pixels, used to compose
19422
- * the executor's crop-normalized child ROI back into frame-normalized
19423
- * coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
19424
- * of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
19425
- * (today's behaviour on the fallback path).
19426
- */
19427
- nativeCropRef: NativeCropRefSchema.optional()
19428
- }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
19429
- engine: PipelineEngineChoiceSchema.optional(),
19430
- steps: array(PipelineStepInputSchema).min(1),
19431
- frames: array(FrameInputSchema).min(1).max(255),
19432
- deviceId: number().optional(),
19433
- sessionId: string().optional(),
19434
- /**
19435
- * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
19436
- * the batch to the Python pool's bench preprocess cache
19437
- * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
19438
- * preprocessed ONCE and every later inference is a pure-inference cache
19439
- * hit — the sustained-throughput run measures inference, not
19440
- * decode+preprocess+infer. Omitted/0 for live frames (all different →
19441
- * full preprocess every call, correct). Fresh per sustained run;
19442
- * released via `uncacheFrame`.
19443
- */
19444
- frameId: number().int().nonnegative().optional(),
19445
- /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
19446
- deviceKey: string().optional()
19447
- }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
19448
- data: _instanceof(Uint8Array),
19449
- width: number().int().positive(),
19450
- height: number().int().positive(),
19451
- format: _enum([
19452
- "rgb",
19453
- "bgr",
19454
- "gray"
19455
- ])
19456
- }), object({
19457
- frameId: number(),
19458
- width: number(),
19459
- height: number()
19460
- }), { kind: "mutation" }), method(object({
19461
- stepId: string(),
19462
- frameId: number().int()
19463
- }), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(_void(), object({
19464
- batchMode: string(),
19465
- windowMs: number(),
19466
- maxBatchSize: number(),
19467
- concurrency: number()
19468
- })), method(_void(), array(object({
19469
- engineKey: string(),
19470
- engine: PipelineEngineChoiceSchema,
19471
- modelsLoaded: array(string()).readonly(),
19472
- inUseByCameras: array(number()).readonly(),
19473
- /**
19474
- * Origin of this resident factory.
19475
- * - `runtime` — main camera-serving engine (no idle TTL).
19476
- * - `warm-override` — benchmark/test override held in the warm
19477
- * cache; auto-disposed after the idle TTL.
19478
- * - `device-pool` — a concurrent per-device pool (Phase 2
19479
- * multi-device, keyed by `deviceKey`) resolved
19480
- * via `resolveDeviceFactory`. Runs alongside the
19481
- * `runtime` engine on a DIFFERENT accelerator
19482
- * (NPU / iGPU / Coral) — this is how the
19483
- * Engines tab shows all pools running at once.
19484
- */
19485
- kind: _enum([
19486
- "runtime",
19487
- "warm-override",
19488
- "device-pool"
19489
- ]),
19490
- /** Native pid of the underlying Python pool (null when no pool). */
19491
- poolPid: number().nullable(),
19492
- /** ms since this factory was last used (null when not warm-tracked). */
19493
- idleMs: number().nullable(),
19494
- /** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
19495
- idleTtlMs: number().nullable()
19496
- })).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
19497
- kind: "mutation",
19498
- auth: "admin"
19499
- }), method(object({
19500
- engine: PipelineEngineChoiceSchema,
19501
- force: boolean().optional()
19502
- }), object({
19503
- success: boolean(),
19504
- reason: string().optional()
19505
- }), {
19506
- kind: "mutation",
19507
- auth: "admin"
19508
- }), method(_void(), array(ReferenceImageEntrySchema).readonly()), method(object({ filename: string() }), ReferenceImageBodySchema.nullable()), method(_void(), array(ReferenceAudioEntrySchema).readonly()), method(object({ filename: string() }), ReferenceAudioBodySchema.nullable()), method(_void(), AudioCapabilitiesSchema), method(object({
19509
- addonId: string(),
19510
- modelId: string(),
19511
- filename: string().optional(),
19512
- settings: record(string(), unknown()).optional()
19513
- }), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
19514
- /**
19515
- * Per-stage gating mode applied to the zones a rule references.
19516
- *
19517
- * - `include`: the rule contributes to a **whitelist** for its stage.
19518
- * When at least one `include` rule fires for a stage, only entities
19519
- * inside one of those zones pass that stage.
19520
- * - `exclude`: the rule contributes to a **blacklist** for its stage.
19521
- * Entities inside one of those zones are dropped at that stage.
19522
- *
19523
- * `monitor`-style observation (count without filtering) is not a rule
19524
- * mode — zones without any matching rule are observed naturally by
19525
- * `zone-analytics` (live snapshot + history), so an "I just want to
19526
- * count, not filter" use case needs no rule at all.
19527
- */
19528
- var ZoneRuleModeEnum = _enum(["include", "exclude"]);
19529
- /**
19530
- * Per-consumer rule that references existing zones (geometry) and
19531
- * defines how a specific pipeline stage should treat them. Each
19532
- * consumer addon owns its own `ZoneRule[]` array in its per-device
19533
- * settings:
19534
- *
19535
- * - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
19536
- * - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
19537
- * - future: notification rules, audio gating, etc.
19538
- *
19539
- * One rule applies to N zones (`zoneIds[]`) so the operator can
19540
- * express "ignore motion in ALL of {garden, street}" with a single
19541
- * rule. `classFilter` narrows the rule to specific object classes —
19542
- * "drop person detections in the street, but keep cars" is one
19543
- * `exclude` rule with `classFilter: ['person']`.
19544
- *
19545
- * `enabled` is a soft toggle — the operator can keep the rule
19546
- * configured but inert without deleting it.
19547
- */
19548
- var ZoneRuleSchema = object({
19549
- /** Stable rule id — survives edits, used by the UI for diffing. */
19550
- id: string(),
19551
- /** Optional human-readable label rendered in the rule editor. */
19552
- name: string().optional(),
19553
- /** Zones this rule targets. The rule's `mode` applies to ALL
19554
- * listed zones (OR-set: a detection in any one of them counts).
19555
- * At least one zone id required — a rule with no targets is a
19556
- * configuration mistake and the form validator rejects it. */
19557
- zoneIds: array(string()).min(1).readonly(),
19558
- mode: ZoneRuleModeEnum,
19559
- /**
19560
- * Class names this rule applies to. Empty / undefined ⇒ rule
19561
- * applies to every class. Class strings match the `macroClass`
19562
- * field on detections (e.g. `person`, `car`, `dog`).
19563
- */
19564
- classFilter: array(string()).readonly().optional(),
19565
- /**
19566
- * Minimum bbox/mask overlap (0–1) with any of the rule's zones
19567
- * required to consider an entity "in the zone". Defaults to the
19568
- * consumer's stage default when omitted. Kept for back-compat with
19569
- * existing per-rule overrides; new operators pick the value via
19570
- * `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
19571
- * set, the lower-level engine reads it as a 0–1 fraction.
19572
- */
19573
- overlapThreshold: number().min(0).max(1).optional(),
19574
- /**
19575
- * Operator-friendly version of `overlapThreshold` — the percentage
19576
- * of the detection's bbox that must lie inside the zone for the
19577
- * rule to match. Documented default is 85%; the engine substitutes
19578
- * that when the field is omitted (kept optional so existing rules
19579
- * stored without it stay valid).
19580
- *
19581
- * When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
19582
- * rule, the engine prefers `bboxInclusionPct` because it's the
19583
- * field exposed in the UI. Internally both feed the same gate.
19584
- */
19585
- bboxInclusionPct: number().min(0).max(100).optional(),
19586
- /**
19587
- * When `true` and a detection has a segmentation mask, use the
19588
- * mask for overlap instead of the bbox. Detection-stage only;
19589
- * motion rules ignore this field.
19590
- */
19591
- preferMask: boolean().optional(),
19592
- /**
19593
- * Soft-toggle: `false` disables the rule without deleting it.
19594
- * Defaults to `true` so operators creating a rule via the UI
19595
- * see it active immediately.
19596
- */
19597
- enabled: boolean().default(true)
19598
- });
19599
- array(ZoneRuleSchema).readonly();
19600
- /**
19601
- * Zone — pure geometry + identity. NO filtering behaviour.
19602
- *
19603
- * Zones describe **where** in the frame the operator wants to flag
19604
- * something; consumer-owned {@link ZoneRule} arrays describe **how**
19605
- * each pipeline stage uses them. Splitting the two means a single
19606
- * polygon "Driveway" can simultaneously back a motion-exclude rule,
19607
- * a detection-include rule on `['car']`, and an occupancy aggregate
19608
- * — without three duplicated polygons.
19609
- *
19610
- * Owned by the orchestrator addon (provider) and mirrored into the
19611
- * `zones` device-state slice on every mutation. Consumers
19612
- * (motion-wasm, pipeline-executor, analytics, admin UI) read either
19613
- * via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
19614
- * mirror with `onChanged`).
19615
- *
19616
- * Coordinates are normalised fractions of the frame (0–1) so zones
19617
- * survive resolution changes and stream profile switches.
19618
- *
19619
- * `kind` discriminates between full polygons (closed regions used
19620
- * for intrusion / occupancy filters) and tripwires (open 2-point
19621
- * line segments used for cross events). Onboard / firmware-reported
19622
- * zones (Reolink, ONVIF) are out of scope for now — see the deferred
19623
- * task list.
19624
- */
19625
- var ZoneKindEnum = _enum(["polygon", "tripwire"]);
19626
- /** Polygon vertex in fraction-of-frame coordinates (0–1). */
19627
- var PolygonPointSchema = object({
19628
- x: number(),
19629
- y: number()
19630
- });
19631
- /** A camera detection zone — pure geometry/identity. */
19632
- var ZoneSchema = object({
19633
- id: string(),
19634
- name: string(),
19635
- kind: ZoneKindEnum.default("polygon"),
19636
- /** Polygon vertices, fraction of frame (0–1). */
19637
- polygon: array(PolygonPointSchema).readonly(),
19638
- /** Visual color for UI rendering. */
19639
- color: string().default("#3b82f6")
19640
- });
19641
- DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).readonly()), method(object({
19642
- deviceId: number(),
19643
- zone: ZoneSchema
19644
- }), _void(), {
19645
- kind: "mutation",
19646
- auth: "admin"
19647
- }), method(object({
19648
- deviceId: number(),
19649
- zoneId: string()
19650
- }), _void(), {
19651
- kind: "mutation",
19652
- auth: "admin"
19653
- }), method(object({
19654
- deviceId: number(),
19655
- zone: ZoneSchema
19656
- }), _void(), {
19657
- kind: "mutation",
19658
- auth: "admin"
19659
- }), object({ zones: array(ZoneSchema).readonly() });
19660
- /**
19661
19148
  * pipeline-analytics — device-scoped wrapper cap. Refines raw
19662
19149
  * per-frame detections emitted by the pipeline runner into tracked
19663
19150
  * objects, per-kind event collections (motion / object / audio), and
@@ -20228,6 +19715,22 @@ var TrackSchema = object({
20228
19715
  * omit it. Render nothing when absent.
20229
19716
  */
20230
19717
  previewMissReason: string().optional(),
19718
+ /**
19719
+ * The ROOT model that produced this track — the `FrameResult.rootModelId` of
19720
+ * the frame it was BORN on (D646). What a later replay compares against, so
19721
+ * "the original model" is named rather than assumed. A birth fact: never
19722
+ * rewritten by a later frame. **Absent ≠ unknown-model**: a row from before
19723
+ * the column, and a track the camera's own detector produced, carry none.
19724
+ */
19725
+ modelId: string().optional(),
19726
+ /**
19727
+ * Size (px) of the detection frame this track's `positions[].bbox` live in —
19728
+ * the frame it was born on, else the camera's latest analysis frame at
19729
+ * persist time. Divide a position by these to normalise it. Absent when the
19730
+ * size was never known.
19731
+ */
19732
+ frameWidth: number().optional(),
19733
+ frameHeight: number().optional(),
20231
19734
  ...TrackFlagFields,
20232
19735
  ...TrackRetrainFields
20233
19736
  });
@@ -21234,24 +20737,6 @@ var MediaReclaimStatusSchema = object({
21234
20737
  finishedAtMs: number().nullable(),
21235
20738
  error: string().nullable()
21236
20739
  });
21237
- var ReplayFrameInputSchema = object({
21238
- timestamp: number(),
21239
- frame: PipelineRunResultBridge
21240
- });
21241
- var RunReplayFrameProcessorResultSchema = object({ tracks: array(object({
21242
- className: string(),
21243
- firstSeenMs: number(),
21244
- lastSeenMs: number(),
21245
- /** Bbox of the track's FIRST matched detection, pixel-space in the clip's
21246
- * frame — a representative box for the diff's `(className, window, IoU)`
21247
- * pairing (`replay-diff.ts`). A replay does not need the full per-frame
21248
- * trajectory production's `Track.positions` keeps. */
21249
- bbox: BoundingBoxSchema,
21250
- /** How many of the input frames this track matched a real detection on
21251
- * (never a coasted/extrapolated frame) — the replay's own signal for "how
21252
- * solid is this track", cheaper than re-deriving it from a trajectory. */
21253
- framesMatched: number().int()
21254
- })).readonly() });
21255
20740
  /**
21256
20741
  * The long-term series a camera produces. A closed union so a typo cannot
21257
20742
  * invent one, and the ONE declaration of it — the addon's `AnalyticsLtsSeries`
@@ -21465,108 +20950,570 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21465
20950
  }), {
21466
20951
  kind: "mutation",
21467
20952
  auth: "admin"
21468
- }), method(object({ frameId: string() }), object({
21469
- base64: string(),
21470
- width: number().int(),
21471
- height: number().int()
20953
+ }), method(object({ frameId: string() }), object({
20954
+ base64: string(),
20955
+ width: number().int(),
20956
+ height: number().int()
20957
+ }), {
20958
+ kind: "query",
20959
+ auth: "admin"
20960
+ }), method(object({
20961
+ deviceId: number(),
20962
+ trackId: string(),
20963
+ frameId: string(),
20964
+ subject: RetrainAssistSubjectSchema,
20965
+ /** Which node runs it. Absent ⇒ wherever an unowned call lands. */
20966
+ nodeId: string().optional()
20967
+ }), RetrainAssistResultSchema, {
20968
+ kind: "mutation",
20969
+ auth: "admin"
20970
+ }), method(object({ trackId: string() }), array(RetrainAnnotationSchema).readonly(), {
20971
+ kind: "query",
20972
+ auth: "admin"
20973
+ }), method(object({
20974
+ deviceId: number(),
20975
+ trackId: string(),
20976
+ frameId: string(),
20977
+ annotations: array(RetrainAnnotationDraftSchema)
20978
+ }), array(RetrainAnnotationSchema).readonly(), {
20979
+ kind: "mutation",
20980
+ auth: "admin"
20981
+ }), method(object({
20982
+ deviceId: number(),
20983
+ trackId: string()
20984
+ }), RetrainTransitionResultSchema, {
20985
+ kind: "mutation",
20986
+ auth: "admin"
20987
+ }), method(object({
20988
+ deviceId: number(),
20989
+ trackId: string()
20990
+ }), RetrainTransitionResultSchema, {
20991
+ kind: "mutation",
20992
+ auth: "admin"
20993
+ }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
20994
+ kind: "query",
20995
+ auth: "admin"
20996
+ }), method(object({
20997
+ /** Which of the three event tables owns the row. */
20998
+ ownerType: EventOwnerTypeSchema,
20999
+ /** The event's rowid in that table (D474: an event id is a number). */
21000
+ eventId: number().int(),
21001
+ kind: MediaFileKindEnum.optional(),
21002
+ deviceId: number()
21003
+ }), array(MediaFileSchema).readonly()), method(object({
21004
+ trackId: string(),
21005
+ kinds: array(MediaFileKindEnum).optional(),
21006
+ deviceId: number()
21007
+ }), array(MediaFileSchema).readonly()), method(object({
21008
+ trackId: string(),
21009
+ deviceId: number()
21010
+ }), array(MediaFileInfoSchema).readonly()), method(object({
21011
+ ownerType: EventOwnerTypeSchema,
21012
+ eventId: number().int(),
21013
+ deviceId: number()
21014
+ }), array(MediaFileInfoSchema).readonly()), method(object({
21015
+ deviceId: number(),
21016
+ ownerKind: MediaPresenceOwnerKindSchema,
21017
+ ownerIds: array(string()).max(5e3)
21018
+ }), array(string()).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
21019
+ kind: "mutation",
21020
+ auth: "admin"
21021
+ }), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
21022
+ kind: "mutation",
21023
+ auth: "admin"
21024
+ }), method(object({}), RebuildStatusSchema), object({
21025
+ deviceId: number(),
21026
+ timestamp: number(),
21027
+ frameWidth: number(),
21028
+ frameHeight: number(),
21029
+ detections: array(OverlayDetectionSchema).readonly()
21030
+ }), object({
21031
+ deviceId: number(),
21032
+ trackId: string(),
21033
+ className: string()
21034
+ }), object({
21035
+ deviceId: number(),
21036
+ trackId: string(),
21037
+ className: string(),
21038
+ durationMs: number()
21039
+ }), object({
21040
+ deviceId: number(),
21041
+ kind: EventKindSchema,
21042
+ eventId: string(),
21043
+ timestamp: number()
21044
+ });
21045
+ /**
21046
+ * Reference to the frame's retained NATIVE surface + the parent crop's placement
21047
+ * within the frame, so the executor can re-cut a leaf child ROI at native
21048
+ * resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
21049
+ */
21050
+ var NativeCropRefSchema = object({
21051
+ /** Handle keying the retained native surface (node-pinned to its owner). */
21052
+ handle: FrameHandleSchema,
21053
+ /** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
21054
+ cropFrameSpace: object({
21055
+ x: number(),
21056
+ y: number(),
21057
+ w: number(),
21058
+ h: number()
21059
+ })
21060
+ });
21061
+ object({
21062
+ crop: object({
21063
+ left: number(),
21064
+ top: number(),
21065
+ width: number().positive(),
21066
+ height: number().positive()
21067
+ }).optional(),
21068
+ content: object({
21069
+ width: number().int().positive(),
21070
+ height: number().int().positive()
21071
+ }),
21072
+ fit: _enum(["stretch", "contain"]),
21073
+ format: _enum([
21074
+ "rgb",
21075
+ "gray",
21076
+ "jpeg"
21077
+ ])
21078
+ });
21079
+ /**
21080
+ * Process-local frame identity. It is serializable so it can ride an in-process
21081
+ * capability call, but `registryId` deliberately prevents resolution in any
21082
+ * other process or execution group.
21083
+ */
21084
+ var FrameRefSchema = object({
21085
+ registryId: string().min(1),
21086
+ id: string().min(1),
21087
+ width: number().int().positive(),
21088
+ height: number().int().positive(),
21089
+ format: _enum(["rgb", "gray"]),
21090
+ timestamp: number(),
21091
+ capturedAt: number().optional()
21092
+ });
21093
+ var ModelFormatSchema$1 = _enum([
21094
+ "onnx",
21095
+ "coreml",
21096
+ "openvino",
21097
+ "tflite",
21098
+ "pt",
21099
+ "gguf"
21100
+ ]);
21101
+ var PipelineSlotSchema = _enum([
21102
+ "detector",
21103
+ "cropper",
21104
+ "classifier",
21105
+ "refiner",
21106
+ "audio-classifier"
21107
+ ]);
21108
+ var PipelineEngineChoiceSchema = object({
21109
+ runtime: literal("python"),
21110
+ backend: string(),
21111
+ format: ModelFormatSchema$1,
21112
+ device: string().optional()
21113
+ });
21114
+ /**
21115
+ * One pool's resolved provisioning (`getEffectiveTuning`). `numWorkers` is the
21116
+ * knob that lifts a saturated pool (`inference-devices.md`); `concurrency` is
21117
+ * per-worker in-flight requests. `deviceKey` echoes the pool asked about —
21118
+ * `null` for the node-default pool.
21119
+ */
21120
+ var EffectiveTuningSchema = object({
21121
+ deviceKey: string().nullable(),
21122
+ runtime: string(),
21123
+ batchMode: string(),
21124
+ windowMs: number(),
21125
+ maxBatchSize: number(),
21126
+ concurrency: number(),
21127
+ numWorkers: number()
21128
+ });
21129
+ var AvailableEngineSchema = object({
21130
+ engine: PipelineEngineChoiceSchema,
21131
+ devices: array(object({
21132
+ id: string(),
21133
+ label: string(),
21134
+ description: string().optional()
21135
+ })).readonly(),
21136
+ defaultDevice: string()
21137
+ });
21138
+ var PipelineDefaultStepSchema = lazy(() => object({
21139
+ addonId: string(),
21140
+ addonName: string(),
21141
+ slot: PipelineSlotSchema,
21142
+ inputClasses: array(string()).readonly(),
21143
+ outputClasses: array(string()).readonly(),
21144
+ enabled: boolean(),
21145
+ modelId: string(),
21146
+ children: array(PipelineDefaultStepSchema).readonly(),
21147
+ group: string().optional(),
21148
+ settings: record(string(), unknown()).optional()
21149
+ }));
21150
+ var PipelineTemplateStepSchema = lazy(() => object({
21151
+ addonId: string(),
21152
+ enabled: boolean(),
21153
+ modelId: string(),
21154
+ children: array(PipelineTemplateStepSchema).readonly(),
21155
+ settings: record(string(), unknown()).optional()
21156
+ }));
21157
+ var PipelineTemplateSchema$1 = object({
21158
+ id: string(),
21159
+ name: string(),
21160
+ createdAt: string(),
21161
+ updatedAt: string(),
21162
+ engine: PipelineEngineChoiceSchema,
21163
+ steps: array(PipelineTemplateStepSchema).readonly()
21164
+ });
21165
+ var PipelineModelOptionSchema = object({
21166
+ id: string(),
21167
+ name: string(),
21168
+ formats: record(string(), object({
21169
+ downloaded: boolean(),
21170
+ sizeMB: number()
21171
+ })),
21172
+ group: ModelVariantGroupSchema.optional(),
21173
+ legacy: boolean().optional(),
21174
+ provider: ModelProviderIdSchema.optional()
21175
+ });
21176
+ var ConfigFieldBridge = custom();
21177
+ var PipelineAddonSchemaSchema = object({
21178
+ id: string(),
21179
+ name: string(),
21180
+ slot: PipelineSlotSchema,
21181
+ inputClasses: array(string()).readonly(),
21182
+ outputClasses: array(string()).readonly(),
21183
+ childSlots: array(PipelineSlotSchema).readonly(),
21184
+ models: array(PipelineModelOptionSchema).readonly(),
21185
+ defaultModelId: string(),
21186
+ defaultModelIdByFormat: record(string(), string()).optional(),
21187
+ enabledByDefault: boolean().optional(),
21188
+ backfillIntoExistingOverrides: boolean().optional(),
21189
+ defaultConfidence: number(),
21190
+ group: string().optional(),
21191
+ configSchema: array(ConfigFieldBridge).readonly().optional()
21192
+ });
21193
+ var PipelineSlotSchemaSchema = object({
21194
+ id: PipelineSlotSchema,
21195
+ label: string(),
21196
+ priority: number(),
21197
+ parentSlot: PipelineSlotSchema.nullable(),
21198
+ addons: array(PipelineAddonSchemaSchema).readonly()
21199
+ });
21200
+ var PipelineSchemaSchema = object({
21201
+ availableEngines: array(AvailableEngineSchema).readonly(),
21202
+ selectedEngine: PipelineEngineChoiceSchema,
21203
+ slots: array(PipelineSlotSchemaSchema).readonly()
21204
+ });
21205
+ var EngineProvisioningSchema = object({
21206
+ runtimeId: _enum([
21207
+ "onnx",
21208
+ "openvino",
21209
+ "coreml",
21210
+ "edgetpu"
21211
+ ]).nullable(),
21212
+ device: string().nullable(),
21213
+ state: _enum([
21214
+ "idle",
21215
+ "installing",
21216
+ "verifying",
21217
+ "ready",
21218
+ "failed"
21219
+ ]),
21220
+ progress: number().optional(),
21221
+ error: string().optional(),
21222
+ nextRetryAt: number().optional(),
21223
+ /**
21224
+ * Gate A (config-correctness gate at engine change): human-readable
21225
+ * config issues surfaced EAGERLY when the node's engine changes — model
21226
+ * substitutions ("chose X, running Y") and zero-build steps ("no model
21227
+ * has a <format> build"). Additive/optional: informational only, never
21228
+ * enforced here — `assertEngineReady` (readiness) still gates inference.
21229
+ * Absent/empty when the node-default tree resolves cleanly.
21230
+ */
21231
+ configIssues: array(string()).optional()
21232
+ });
21233
+ var PipelineStepInputSchema = lazy(() => object({
21234
+ addonId: string(),
21235
+ modelId: string().optional(),
21236
+ enabled: boolean().default(true),
21237
+ children: array(PipelineStepInputSchema).optional(),
21238
+ settings: record(string(), unknown()).optional(),
21239
+ jumpDeviceKey: string().optional()
21240
+ }));
21241
+ var ModelSubstitutionSchema = object({
21242
+ addonId: string(),
21243
+ chosen: string(),
21244
+ running: string(),
21245
+ format: string()
21246
+ });
21247
+ var PipelineValidationIssueSchema = object({
21248
+ addonId: string(),
21249
+ kind: _enum([
21250
+ "unknown-addon",
21251
+ "no-format-build",
21252
+ "unknown-device"
21253
+ ]),
21254
+ detail: string()
21255
+ });
21256
+ var PipelineValidationResultSchema = object({
21257
+ ok: boolean(),
21258
+ issues: array(PipelineValidationIssueSchema).readonly(),
21259
+ substitutions: array(ModelSubstitutionSchema).readonly(),
21260
+ /** The node's `currentEngine.format` this validation ran against. */
21261
+ format: string()
21262
+ });
21263
+ var ReferenceImageEntrySchema = object({
21264
+ filename: string(),
21265
+ stepIds: array(string()).readonly().optional()
21266
+ });
21267
+ var ReferenceImageBodySchema = object({
21268
+ base64: string(),
21269
+ filename: string()
21270
+ });
21271
+ var ReferenceAudioEntrySchema = object({
21272
+ filename: string(),
21273
+ sizeKb: number()
21274
+ });
21275
+ var ReferenceAudioBodySchema = object({ base64: string() });
21276
+ var AudioBackendSchema = object({
21277
+ id: string(),
21278
+ name: string(),
21279
+ description: string(),
21280
+ available: boolean(),
21281
+ /**
21282
+ * Raw classifier labels this backend can emit (e.g. YAMNet's
21283
+ * 521-class set or Apple SoundAnalysis's 303-class set). Used by
21284
+ * the benchmark UI to populate the `enabledMicroClasses` filter
21285
+ * specific to the selected backend without a separate fetch.
21286
+ */
21287
+ rawLabels: array(string()).readonly().optional()
21288
+ });
21289
+ var AudioCapabilitiesSchema = object({
21290
+ activeBackend: string(),
21291
+ availableBackends: array(AudioBackendSchema).readonly(),
21292
+ sampleRate: number(),
21293
+ chunkDurationMs: number()
21294
+ });
21295
+ var DownloadModelResultSchema = object({
21296
+ filePath: string(),
21297
+ sizeMB: number(),
21298
+ durationMs: number()
21299
+ });
21300
+ /**
21301
+ * Wrapper carrying a single test run's result. Replaces the legacy
21302
+ * ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
21303
+ * canonical `AudioResult` from the Phase 6 output rework: one
21304
+ * `AudioDetection` per class above `minScore`, top-N candidates in
21305
+ * `debug.alternateLabels['audio-classifier']`, per-source timings in
21306
+ * `debug.stepTimings`. The outer `success`/`error` fields stay so the
21307
+ * benchmark UI can still report a clean failure when the classifier
21308
+ * cap isn't available.
21309
+ */
21310
+ var AudioTestResultSchema = object({
21311
+ success: boolean(),
21312
+ error: string().optional(),
21313
+ frame: custom().optional()
21314
+ });
21315
+ var PipelineConfigBridge = custom();
21316
+ var ConfigUISchemaBridge = custom();
21317
+ var ConfigUISchemaNullableBridge = custom();
21318
+ var InferenceCapabilitiesBridge = custom();
21319
+ var ModelAvailabilityListBridge = custom();
21320
+ var PipelineRunResultBridge = custom();
21321
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
21322
+ modelId: string(),
21323
+ settings: record(string(), unknown()).readonly()
21324
+ }))), method(object({ steps: record(string(), object({
21325
+ modelId: string(),
21326
+ settings: record(string(), unknown()).readonly()
21327
+ })) }), object({ success: literal(true) }), {
21328
+ kind: "mutation",
21329
+ auth: "admin"
21330
+ }), method(object({ nodeId: string() }), object({
21331
+ success: literal(true),
21332
+ clearedDevices: number()
21472
21333
  }), {
21473
- kind: "query",
21474
- auth: "admin"
21475
- }), method(object({
21476
- deviceId: number(),
21477
- trackId: string(),
21478
- frameId: string(),
21479
- subject: RetrainAssistSubjectSchema,
21480
- /** Which node runs it. Absent ⇒ wherever an unowned call lands. */
21481
- nodeId: string().optional()
21482
- }), RetrainAssistResultSchema, {
21483
- kind: "mutation",
21484
- auth: "admin"
21485
- }), method(object({
21486
- deviceId: number(),
21487
- source: DetectionSourceSchema,
21488
- zones: array(ZoneSchema).readonly().optional(),
21489
- detectionRules: array(ZoneRuleSchema).readonly().optional(),
21490
- zoneMembershipMinOverlap: number().min(0).max(1).optional(),
21491
- frames: array(ReplayFrameInputSchema).min(1)
21492
- }), RunReplayFrameProcessorResultSchema, {
21493
- kind: "mutation",
21494
- auth: "admin"
21495
- }), method(object({ trackId: string() }), array(RetrainAnnotationSchema).readonly(), {
21496
- kind: "query",
21497
- auth: "admin"
21498
- }), method(object({
21499
- deviceId: number(),
21500
- trackId: string(),
21501
- frameId: string(),
21502
- annotations: array(RetrainAnnotationDraftSchema)
21503
- }), array(RetrainAnnotationSchema).readonly(), {
21504
21334
  kind: "mutation",
21505
21335
  auth: "admin"
21506
- }), method(object({
21507
- deviceId: number(),
21508
- trackId: string()
21509
- }), RetrainTransitionResultSchema, {
21336
+ }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
21337
+ /** `<backend>:<device>`, e.g. `openvino:gpu`. */
21338
+ deviceKey: string(),
21339
+ /**
21340
+ * `failed` — the per-device restart budget is exhausted; no pool
21341
+ * will be spawned until an operator re-arms it or the runner
21342
+ * respawns. `backoff` — under budget, waiting out the backoff (or
21343
+ * a cached pool observed dead and not yet condemned).
21344
+ */
21345
+ state: _enum(["failed", "backoff"]),
21346
+ /** Epoch ms of the death that produced this state. */
21347
+ since: number(),
21348
+ /** Pool deaths inside the current window. */
21349
+ deaths: number(),
21350
+ /** The last death's message. */
21351
+ lastError: string()
21352
+ })).readonly() })), method(object({
21353
+ nodeId: string(),
21354
+ deviceKey: string()
21355
+ }), object({ rearmed: boolean() }), {
21510
21356
  kind: "mutation",
21511
21357
  auth: "admin"
21512
- }), method(object({
21513
- deviceId: number(),
21514
- trackId: string()
21515
- }), RetrainTransitionResultSchema, {
21358
+ }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
21359
+ steps: array(PipelineStepInputSchema),
21360
+ deviceKey: string().optional()
21361
+ }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
21362
+ name: string(),
21363
+ steps: array(PipelineTemplateStepSchema).readonly(),
21364
+ engine: PipelineEngineChoiceSchema
21365
+ }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
21366
+ id: string(),
21367
+ name: string().optional(),
21368
+ steps: array(PipelineTemplateStepSchema).readonly().optional()
21369
+ }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
21370
+ addonId: string(),
21371
+ modelId: string(),
21372
+ format: ModelFormatSchema$1
21373
+ }), DownloadModelResultSchema, { kind: "mutation" }), method(object({
21374
+ addonId: string(),
21375
+ modelId: string(),
21376
+ format: ModelFormatSchema$1
21377
+ }), object({ success: literal(true) }), { kind: "mutation" }), method(object({
21378
+ steps: array(PipelineStepInputSchema).min(1),
21379
+ frame: FrameInputSchema.optional(),
21380
+ /**
21381
+ * Process-local lazy frame. Valid only when caller and provider resolve
21382
+ * in the same execution-group process; split/cross-node callers use
21383
+ * `frame`/`image` inline compatibility instead.
21384
+ */
21385
+ frameRef: FrameRefSchema.optional(),
21386
+ /**
21387
+ * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
21388
+ * the decoded pixels live in. One more member of the one-of
21389
+ * frame/frameHandle/image/imageBase64/referenceImage group.
21390
+ */
21391
+ frameHandle: FrameHandleSchema.optional(),
21392
+ imageBase64: string().optional(),
21393
+ /**
21394
+ * Binary JPEG bytes — preferred over `imageBase64` on internal
21395
+ * hops (hub → forked worker via Moleculer MsgPack) because it
21396
+ * skips the 33% base64 overhead + the per-call base64 decode on
21397
+ * the detection-pipeline worker. Callers can pass either; exactly
21398
+ * one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
21399
+ */
21400
+ image: _instanceof(Uint8Array).optional(),
21401
+ referenceImage: string().optional(),
21402
+ deviceId: number().optional(),
21403
+ sessionId: string().optional(),
21404
+ /**
21405
+ * Execution plane. 'full' (default) runs the whole tree — benchmark,
21406
+ * reference-image, and detail-subtree calls. 'frame' is the live
21407
+ * per-frame dispatch: ONLY root-plane steps run; crop children
21408
+ * (inputClasses ≠ null) are skipped and served per-track via
21409
+ * pipelineRunner.runDetailSubtree (two-plane design).
21410
+ */
21411
+ plane: _enum(["full", "frame"]).optional(),
21412
+ /**
21413
+ * Inference-device selector (Phase 2 multi-device). Format
21414
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
21415
+ * Omitted ⇒ the runner's default device (current single-engine
21416
+ * behaviour). Selects WHICH device pool of the node runs the call.
21417
+ */
21418
+ deviceKey: string().optional(),
21419
+ /**
21420
+ * Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
21421
+ * when the parent crop was resolved from the frame's retained NATIVE
21422
+ * surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
21423
+ * child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
21424
+ * resolution from that surface — the SAME quality path faces already
21425
+ * had — instead of the downscaled parent tile. `handle` keys the native
21426
+ * surface (node-pinned to its owner); `cropFrameSpace` is the parent
21427
+ * crop's padded/clamped rectangle in FRAME-space pixels, used to compose
21428
+ * the executor's crop-normalized child ROI back into frame-normalized
21429
+ * coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
21430
+ * of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
21431
+ * (today's behaviour on the fallback path).
21432
+ */
21433
+ nativeCropRef: NativeCropRefSchema.optional(),
21434
+ /**
21435
+ * Offline REPLAY of stored media for `deviceId` (D56, D646): the
21436
+ * camera's zone gate and overrides apply as live, every executing
21437
+ * step runs EXACTLY the model it names on the `deviceKey` pool it
21438
+ * names or the call refuses (`model-not-servable` /
21439
+ * `device-not-servable`), and nothing reaches the camera's live
21440
+ * trace stream. Absent ⇒ unchanged behaviour.
21441
+ */
21442
+ replay: literal(true).optional()
21443
+ }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
21444
+ steps: array(PipelineStepInputSchema).min(1),
21445
+ frames: array(FrameInputSchema).min(1).max(255),
21446
+ deviceId: number().optional(),
21447
+ sessionId: string().optional(),
21448
+ /**
21449
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
21450
+ * the batch to the Python pool's bench preprocess cache
21451
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
21452
+ * preprocessed ONCE and every later inference is a pure-inference cache
21453
+ * hit — the sustained-throughput run measures inference, not
21454
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
21455
+ * full preprocess every call, correct). Fresh per sustained run;
21456
+ * released via `uncacheFrame`.
21457
+ */
21458
+ frameId: number().int().nonnegative().optional(),
21459
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
21460
+ deviceKey: string().optional()
21461
+ }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
21462
+ data: _instanceof(Uint8Array),
21463
+ width: number().int().positive(),
21464
+ height: number().int().positive(),
21465
+ format: _enum([
21466
+ "rgb",
21467
+ "bgr",
21468
+ "gray"
21469
+ ])
21470
+ }), object({
21471
+ frameId: number(),
21472
+ width: number(),
21473
+ height: number()
21474
+ }), { kind: "mutation" }), method(object({
21475
+ stepId: string(),
21476
+ frameId: number().int()
21477
+ }), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(object({ deviceKey: string().optional() }), EffectiveTuningSchema), method(_void(), array(object({
21478
+ engineKey: string(),
21479
+ engine: PipelineEngineChoiceSchema,
21480
+ modelsLoaded: array(string()).readonly(),
21481
+ inUseByCameras: array(number()).readonly(),
21482
+ /**
21483
+ * Origin of this resident factory.
21484
+ * - `runtime` — main camera-serving engine (no idle TTL).
21485
+ * - `device-pool` — a concurrent per-device pool (Phase 2
21486
+ * multi-device, keyed by `deviceKey`) resolved
21487
+ * via `resolveDeviceFactory`. Runs alongside the
21488
+ * `runtime` engine on a DIFFERENT accelerator
21489
+ * (NPU / iGPU / Coral) — this is how the
21490
+ * Engines tab shows all pools running at once.
21491
+ */
21492
+ kind: _enum(["runtime", "device-pool"]),
21493
+ /** Native pid of the underlying Python pool (null when no pool). */
21494
+ poolPid: number().nullable(),
21495
+ /** ms since this factory was last used (null when not warm-tracked). */
21496
+ idleMs: number().nullable(),
21497
+ /** Idle TTL after which the factory self-evicts (null when not applicable). */
21498
+ idleTtlMs: number().nullable()
21499
+ })).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
21516
21500
  kind: "mutation",
21517
21501
  auth: "admin"
21518
- }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
21519
- kind: "query",
21520
- auth: "admin"
21521
21502
  }), method(object({
21522
- /** Which of the three event tables owns the row. */
21523
- ownerType: EventOwnerTypeSchema,
21524
- /** The event's rowid in that table (D474: an event id is a number). */
21525
- eventId: number().int(),
21526
- kind: MediaFileKindEnum.optional(),
21527
- deviceId: number()
21528
- }), array(MediaFileSchema).readonly()), method(object({
21529
- trackId: string(),
21530
- kinds: array(MediaFileKindEnum).optional(),
21531
- deviceId: number()
21532
- }), array(MediaFileSchema).readonly()), method(object({
21533
- trackId: string(),
21534
- deviceId: number()
21535
- }), array(MediaFileInfoSchema).readonly()), method(object({
21536
- ownerType: EventOwnerTypeSchema,
21537
- eventId: number().int(),
21538
- deviceId: number()
21539
- }), array(MediaFileInfoSchema).readonly()), method(object({
21540
- deviceId: number(),
21541
- ownerKind: MediaPresenceOwnerKindSchema,
21542
- ownerIds: array(string()).max(5e3)
21543
- }), array(string()).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
21544
- kind: "mutation",
21545
- auth: "admin"
21546
- }), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
21503
+ engine: PipelineEngineChoiceSchema,
21504
+ force: boolean().optional()
21505
+ }), object({
21506
+ success: boolean(),
21507
+ reason: string().optional()
21508
+ }), {
21547
21509
  kind: "mutation",
21548
21510
  auth: "admin"
21549
- }), method(object({}), RebuildStatusSchema), object({
21550
- deviceId: number(),
21551
- timestamp: number(),
21552
- frameWidth: number(),
21553
- frameHeight: number(),
21554
- detections: array(OverlayDetectionSchema).readonly()
21555
- }), object({
21556
- deviceId: number(),
21557
- trackId: string(),
21558
- className: string()
21559
- }), object({
21560
- deviceId: number(),
21561
- trackId: string(),
21562
- className: string(),
21563
- durationMs: number()
21564
- }), object({
21565
- deviceId: number(),
21566
- kind: EventKindSchema,
21567
- eventId: string(),
21568
- timestamp: number()
21569
- });
21511
+ }), method(_void(), array(ReferenceImageEntrySchema).readonly()), method(object({ filename: string() }), ReferenceImageBodySchema.nullable()), method(_void(), array(ReferenceAudioEntrySchema).readonly()), method(object({ filename: string() }), ReferenceAudioBodySchema.nullable()), method(_void(), AudioCapabilitiesSchema), method(object({
21512
+ addonId: string(),
21513
+ modelId: string(),
21514
+ filename: string().optional(),
21515
+ settings: record(string(), unknown()).optional()
21516
+ }), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
21570
21517
  object({
21571
21518
  activeCameras: number(),
21572
21519
  throttledCameras: number(),
@@ -21592,6 +21539,66 @@ var CameraMetricsSchema = object({
21592
21539
  });
21593
21540
  var CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({ deviceId: number() });
21594
21541
  /**
21542
+ * Zone — pure geometry + identity. NO filtering behaviour.
21543
+ *
21544
+ * Zones describe **where** in the frame the operator wants to flag
21545
+ * something; consumer-owned {@link ZoneRule} arrays describe **how**
21546
+ * each pipeline stage uses them. Splitting the two means a single
21547
+ * polygon "Driveway" can simultaneously back a motion-exclude rule,
21548
+ * a detection-include rule on `['car']`, and an occupancy aggregate
21549
+ * — without three duplicated polygons.
21550
+ *
21551
+ * Owned by the orchestrator addon (provider) and mirrored into the
21552
+ * `zones` device-state slice on every mutation. Consumers
21553
+ * (motion-wasm, pipeline-executor, analytics, admin UI) read either
21554
+ * via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
21555
+ * mirror with `onChanged`).
21556
+ *
21557
+ * Coordinates are normalised fractions of the frame (0–1) so zones
21558
+ * survive resolution changes and stream profile switches.
21559
+ *
21560
+ * `kind` discriminates between full polygons (closed regions used
21561
+ * for intrusion / occupancy filters) and tripwires (open 2-point
21562
+ * line segments used for cross events). Onboard / firmware-reported
21563
+ * zones (Reolink, ONVIF) are out of scope for now — see the deferred
21564
+ * task list.
21565
+ */
21566
+ var ZoneKindEnum = _enum(["polygon", "tripwire"]);
21567
+ /** Polygon vertex in fraction-of-frame coordinates (0–1). */
21568
+ var PolygonPointSchema = object({
21569
+ x: number(),
21570
+ y: number()
21571
+ });
21572
+ /** A camera detection zone — pure geometry/identity. */
21573
+ var ZoneSchema = object({
21574
+ id: string(),
21575
+ name: string(),
21576
+ kind: ZoneKindEnum.default("polygon"),
21577
+ /** Polygon vertices, fraction of frame (0–1). */
21578
+ polygon: array(PolygonPointSchema).readonly(),
21579
+ /** Visual color for UI rendering. */
21580
+ color: string().default("#3b82f6")
21581
+ });
21582
+ DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).readonly()), method(object({
21583
+ deviceId: number(),
21584
+ zone: ZoneSchema
21585
+ }), _void(), {
21586
+ kind: "mutation",
21587
+ auth: "admin"
21588
+ }), method(object({
21589
+ deviceId: number(),
21590
+ zoneId: string()
21591
+ }), _void(), {
21592
+ kind: "mutation",
21593
+ auth: "admin"
21594
+ }), method(object({
21595
+ deviceId: number(),
21596
+ zone: ZoneSchema
21597
+ }), _void(), {
21598
+ kind: "mutation",
21599
+ auth: "admin"
21600
+ }), object({ zones: array(ZoneSchema).readonly() });
21601
+ /**
21595
21602
  * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
21596
21603
  * decode worker resolves it against the RETAINED native frame's real pixel dims,
21597
21604
  * so the caller supplies only the detection-res bbox divided by the detection
@@ -30113,7 +30120,7 @@ var HardwareInfoSchema = object({
30113
30120
  coral: CoralInfoSchema.nullable().optional()
30114
30121
  });
30115
30122
  var PlatformScoreSchema = object({
30116
- runtime: _enum(["node", "python"]),
30123
+ runtime: literal("python"),
30117
30124
  backend: string(),
30118
30125
  format: _enum([
30119
30126
  "onnx",
@@ -30150,7 +30157,7 @@ var ModelRequirementSchema = object({
30150
30157
  });
30151
30158
  var ResolvedInferenceConfigSchema = object({
30152
30159
  modelId: string(),
30153
- runtime: _enum(["node", "python"]),
30160
+ runtime: literal("python"),
30154
30161
  backend: string(),
30155
30162
  format: ModelFormatSchema,
30156
30163
  reason: string()
@@ -32357,6 +32364,92 @@ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSche
32357
32364
  kind: "mutation",
32358
32365
  auth: "admin"
32359
32366
  });
32367
+ /**
32368
+ * Per-stage gating mode applied to the zones a rule references.
32369
+ *
32370
+ * - `include`: the rule contributes to a **whitelist** for its stage.
32371
+ * When at least one `include` rule fires for a stage, only entities
32372
+ * inside one of those zones pass that stage.
32373
+ * - `exclude`: the rule contributes to a **blacklist** for its stage.
32374
+ * Entities inside one of those zones are dropped at that stage.
32375
+ *
32376
+ * `monitor`-style observation (count without filtering) is not a rule
32377
+ * mode — zones without any matching rule are observed naturally by
32378
+ * `zone-analytics` (live snapshot + history), so an "I just want to
32379
+ * count, not filter" use case needs no rule at all.
32380
+ */
32381
+ var ZoneRuleModeEnum = _enum(["include", "exclude"]);
32382
+ /**
32383
+ * Per-consumer rule that references existing zones (geometry) and
32384
+ * defines how a specific pipeline stage should treat them. Each
32385
+ * consumer addon owns its own `ZoneRule[]` array in its per-device
32386
+ * settings:
32387
+ *
32388
+ * - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
32389
+ * - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
32390
+ * - future: notification rules, audio gating, etc.
32391
+ *
32392
+ * One rule applies to N zones (`zoneIds[]`) so the operator can
32393
+ * express "ignore motion in ALL of {garden, street}" with a single
32394
+ * rule. `classFilter` narrows the rule to specific object classes —
32395
+ * "drop person detections in the street, but keep cars" is one
32396
+ * `exclude` rule with `classFilter: ['person']`.
32397
+ *
32398
+ * `enabled` is a soft toggle — the operator can keep the rule
32399
+ * configured but inert without deleting it.
32400
+ */
32401
+ var ZoneRuleSchema = object({
32402
+ /** Stable rule id — survives edits, used by the UI for diffing. */
32403
+ id: string(),
32404
+ /** Optional human-readable label rendered in the rule editor. */
32405
+ name: string().optional(),
32406
+ /** Zones this rule targets. The rule's `mode` applies to ALL
32407
+ * listed zones (OR-set: a detection in any one of them counts).
32408
+ * At least one zone id required — a rule with no targets is a
32409
+ * configuration mistake and the form validator rejects it. */
32410
+ zoneIds: array(string()).min(1).readonly(),
32411
+ mode: ZoneRuleModeEnum,
32412
+ /**
32413
+ * Class names this rule applies to. Empty / undefined ⇒ rule
32414
+ * applies to every class. Class strings match the `macroClass`
32415
+ * field on detections (e.g. `person`, `car`, `dog`).
32416
+ */
32417
+ classFilter: array(string()).readonly().optional(),
32418
+ /**
32419
+ * Minimum bbox/mask overlap (0–1) with any of the rule's zones
32420
+ * required to consider an entity "in the zone". Defaults to the
32421
+ * consumer's stage default when omitted. Kept for back-compat with
32422
+ * existing per-rule overrides; new operators pick the value via
32423
+ * `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
32424
+ * set, the lower-level engine reads it as a 0–1 fraction.
32425
+ */
32426
+ overlapThreshold: number().min(0).max(1).optional(),
32427
+ /**
32428
+ * Operator-friendly version of `overlapThreshold` — the percentage
32429
+ * of the detection's bbox that must lie inside the zone for the
32430
+ * rule to match. Documented default is 85%; the engine substitutes
32431
+ * that when the field is omitted (kept optional so existing rules
32432
+ * stored without it stay valid).
32433
+ *
32434
+ * When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
32435
+ * rule, the engine prefers `bboxInclusionPct` because it's the
32436
+ * field exposed in the UI. Internally both feed the same gate.
32437
+ */
32438
+ bboxInclusionPct: number().min(0).max(100).optional(),
32439
+ /**
32440
+ * When `true` and a detection has a segmentation mask, use the
32441
+ * mask for overlap instead of the bbox. Detection-stage only;
32442
+ * motion rules ignore this field.
32443
+ */
32444
+ preferMask: boolean().optional(),
32445
+ /**
32446
+ * Soft-toggle: `false` disables the rule without deleting it.
32447
+ * Defaults to `true` so operators creating a rule via the UI
32448
+ * see it active immediately.
32449
+ */
32450
+ enabled: boolean().default(true)
32451
+ });
32452
+ array(ZoneRuleSchema).readonly();
32360
32453
  object({
32361
32454
  /** Whether the script is currently executing. */
32362
32455
  isRunning: boolean(),
@@ -38709,6 +38802,12 @@ Object.freeze({
38709
38802
  addonId: null,
38710
38803
  access: "view"
38711
38804
  },
38805
+ "notificationRules.previewStateSummary": {
38806
+ capName: "notification-rules",
38807
+ capScope: "system",
38808
+ addonId: null,
38809
+ access: "view"
38810
+ },
38712
38811
  "notificationRules.previewTemplate": {
38713
38812
  capName: "notification-rules",
38714
38813
  capScope: "system",
@@ -39285,12 +39384,6 @@ Object.freeze({
39285
39384
  addonId: null,
39286
39385
  access: "create"
39287
39386
  },
39288
- "pipelineAnalytics.runReplayFrameProcessor": {
39289
- capName: "pipeline-analytics",
39290
- capScope: "device",
39291
- addonId: null,
39292
- access: "create"
39293
- },
39294
39387
  "pipelineAnalytics.saveRetrainAnnotations": {
39295
39388
  capName: "pipeline-analytics",
39296
39389
  capScope: "device",
@@ -43388,11 +43481,6 @@ Object.freeze({
43388
43481
  form: "single",
43389
43482
  optional: false
43390
43483
  }],
43391
- "pipelineAnalytics.runReplayFrameProcessor": [{
43392
- name: "deviceId",
43393
- form: "single",
43394
- optional: false
43395
- }],
43396
43484
  "pipelineAnalytics.saveRetrainAnnotations": [{
43397
43485
  name: "deviceId",
43398
43486
  form: "single",
@@ -44372,6 +44460,98 @@ new Map(Object.entries({
44372
44460
  "camera-enabled": null
44373
44461
  }));
44374
44462
  [...NC_SYSTEM_EVENT_FILTER_KEYS];
44463
+ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
44464
+ {
44465
+ id: "device-state",
44466
+ family: "device-events",
44467
+ label: "Device state",
44468
+ kinds: [
44469
+ "device-offline",
44470
+ "device-online",
44471
+ "device-disabled",
44472
+ "device-enabled"
44473
+ ]
44474
+ },
44475
+ {
44476
+ id: "streams",
44477
+ family: "device-events",
44478
+ label: "Streams",
44479
+ kinds: ["stream-offline", "stream-online"]
44480
+ },
44481
+ {
44482
+ id: "battery",
44483
+ family: "device-events",
44484
+ label: "Battery",
44485
+ kinds: ["device-battery-low", "device-battery-normal"]
44486
+ },
44487
+ {
44488
+ id: "consumables",
44489
+ family: "device-events",
44490
+ label: "Consumables",
44491
+ kinds: ["device-consumable-low", "device-consumable-normal"]
44492
+ },
44493
+ {
44494
+ id: "tanks",
44495
+ family: "device-events",
44496
+ label: "Tanks",
44497
+ kinds: [
44498
+ "device-tank-low",
44499
+ "device-tank-full",
44500
+ "device-tank-normal"
44501
+ ]
44502
+ },
44503
+ {
44504
+ id: "detection-blind",
44505
+ family: "device-events",
44506
+ label: "Detecting nothing",
44507
+ kinds: ["detection-blind"]
44508
+ },
44509
+ {
44510
+ id: "nodes",
44511
+ family: "system",
44512
+ label: "Nodes",
44513
+ kinds: [
44514
+ "node-offline",
44515
+ "node-online",
44516
+ "node-inference-unavailable"
44517
+ ]
44518
+ },
44519
+ {
44520
+ id: "addons",
44521
+ family: "system",
44522
+ label: "Addons",
44523
+ kinds: [
44524
+ "addon-crash-loop",
44525
+ "addon-update-available",
44526
+ "addon-updated"
44527
+ ]
44528
+ },
44529
+ {
44530
+ id: "updates",
44531
+ family: "system",
44532
+ label: "Server & container updates",
44533
+ kinds: [
44534
+ "server-update-available",
44535
+ "server-updated",
44536
+ "wrapper-update-available"
44537
+ ]
44538
+ },
44539
+ {
44540
+ id: "backups-exports",
44541
+ family: "system",
44542
+ label: "Backups & exports",
44543
+ kinds: ["backup-completed", "export-completed"]
44544
+ },
44545
+ {
44546
+ id: "alarm",
44547
+ family: "alarm",
44548
+ label: "Alarm",
44549
+ kinds: NC_ALARM_SYSTEM_EVENT_KINDS
44550
+ }
44551
+ ];
44552
+ function systemEventKindsOfFamily(family) {
44553
+ return NC_SYSTEM_EVENT_KIND_GROUP_SPECS.filter((g) => g.family === family).flatMap((g) => g.kinds);
44554
+ }
44375
44555
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
44376
44556
  /**
44377
44557
  * WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
@@ -44446,7 +44626,183 @@ var DEVICE_EVENTS = [
44446
44626
  "detection-blind",
44447
44627
  ...ALARM
44448
44628
  ];
44449
- [...DEVICE_EVENTS], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_BODY_ONLY], [...RULE_TEXT], [...RULE_TEXT], [...DEVICE_EVENTS], [...RULE_TEXT], [...DEVICE_EVENTS], [...RULE_TEXT], [...BATTERY, ...CONSUMABLE], [...RULE_TEXT], [...CONSUMABLE], [...RULE_TEXT], [...TANK], [...RULE_TEXT], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT];
44629
+ /** Every kind a summary may speak about — the two summarisable families. */
44630
+ var SUMMARISABLE = [...systemEventKindsOfFamily("device-events"), ...systemEventKindsOfFamily("system")];
44631
+ /** One per summary SECTION (`NC_STATE_SUMMARY_SECTIONS` in the notification
44632
+ * centre): the section's lines, offered when one of its kinds is selected. */
44633
+ var STATE_SUMMARY_SECTION_VARS = [
44634
+ {
44635
+ name: "summaryDevices",
44636
+ label: "Summary: devices offline / switched off",
44637
+ example: "Garage — offline since 07:12",
44638
+ kinds: [
44639
+ "device-offline",
44640
+ "device-online",
44641
+ "device-disabled",
44642
+ "device-enabled"
44643
+ ]
44644
+ },
44645
+ {
44646
+ name: "summaryStreams",
44647
+ label: "Summary: streams offline",
44648
+ example: "Ingresso (high) — since 06:40",
44649
+ kinds: ["stream-offline", "stream-online"]
44650
+ },
44651
+ {
44652
+ name: "summaryBattery",
44653
+ label: "Summary: low batteries",
44654
+ example: "Sensore porta — 8 %",
44655
+ kinds: BATTERY
44656
+ },
44657
+ {
44658
+ name: "summaryConsumables",
44659
+ label: "Summary: consumables",
44660
+ example: "Robot — filter 10 %",
44661
+ kinds: CONSUMABLE
44662
+ },
44663
+ {
44664
+ name: "summaryTanks",
44665
+ label: "Summary: tanks",
44666
+ example: "Robot — clean water low",
44667
+ kinds: TANK
44668
+ },
44669
+ {
44670
+ name: "summaryDetection",
44671
+ label: "Summary: cameras detecting nothing",
44672
+ example: "Ingresso — since 05:10",
44673
+ kinds: ["detection-blind"]
44674
+ },
44675
+ {
44676
+ name: "summaryNodes",
44677
+ label: "Summary: nodes",
44678
+ example: "little-unraid — offline since 03:00",
44679
+ kinds: [
44680
+ "node-offline",
44681
+ "node-online",
44682
+ "node-inference-unavailable"
44683
+ ]
44684
+ },
44685
+ {
44686
+ name: "summaryAddons",
44687
+ label: "Summary: addons",
44688
+ example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
44689
+ kinds: [
44690
+ "addon-crash-loop",
44691
+ "addon-update-available",
44692
+ "addon-updated"
44693
+ ]
44694
+ },
44695
+ {
44696
+ name: "summaryUpdates",
44697
+ label: "Summary: server & container updates",
44698
+ example: "server 1.2.377 → 1.2.378",
44699
+ kinds: [
44700
+ "server-update-available",
44701
+ "server-updated",
44702
+ "wrapper-update-available"
44703
+ ]
44704
+ }
44705
+ ];
44706
+ var STATE_SUMMARY_VARS = [
44707
+ {
44708
+ name: "summaryText",
44709
+ label: "Summary: every section",
44710
+ description: "One block per section with something to report, one line per item.",
44711
+ example: "Batterie scariche: Sensore porta — 8 %",
44712
+ group: "system",
44713
+ families: ["rule"],
44714
+ fields: [...RULE_TEXT],
44715
+ kinds: ["system"],
44716
+ systemEventKinds: [...SUMMARISABLE],
44717
+ systemEventDeliveries: ["summary"]
44718
+ },
44719
+ {
44720
+ name: "summaryCount",
44721
+ label: "Summary: items reported",
44722
+ example: "3",
44723
+ group: "system",
44724
+ families: ["rule"],
44725
+ fields: [...RULE_TEXT],
44726
+ kinds: ["system"],
44727
+ systemEventKinds: [...SUMMARISABLE],
44728
+ systemEventDeliveries: ["summary"]
44729
+ },
44730
+ ...STATE_SUMMARY_SECTION_VARS.map((v) => ({
44731
+ name: v.name,
44732
+ label: v.label,
44733
+ example: v.example,
44734
+ group: "system",
44735
+ families: ["rule"],
44736
+ fields: [...RULE_TEXT],
44737
+ kinds: ["system"],
44738
+ systemEventKinds: [...v.kinds],
44739
+ systemEventDeliveries: ["summary"]
44740
+ }))
44741
+ ];
44742
+ [
44743
+ [...DEVICE_EVENTS],
44744
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
44745
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
44746
+ [...RULE_TEXT],
44747
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
44748
+ ([...RULE_TEXT], [...PACKAGE_UPDATES]),
44749
+ [...RULE_TEXT],
44750
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
44751
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
44752
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
44753
+ [...RULE_TEXT],
44754
+ [...RULE_TEXT],
44755
+ [...RULE_TEXT],
44756
+ [...RULE_TEXT],
44757
+ [...RULE_TEXT],
44758
+ [...RULE_TEXT],
44759
+ [...RULE_TEXT],
44760
+ [...RULE_TEXT],
44761
+ [...RULE_BODY_ONLY],
44762
+ [...RULE_TEXT],
44763
+ ([...RULE_TEXT], [...DEVICE_EVENTS]),
44764
+ ([...RULE_TEXT], [...DEVICE_EVENTS]),
44765
+ ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
44766
+ ([...RULE_TEXT], [...CONSUMABLE]),
44767
+ ([...RULE_TEXT], [...TANK]),
44768
+ [...RULE_TEXT],
44769
+ ([...RULE_TEXT], [...UPDATES]),
44770
+ ([...RULE_TEXT], [...UPDATES]),
44771
+ [...RULE_TEXT],
44772
+ [...RULE_TEXT],
44773
+ [...RULE_TEXT],
44774
+ ([...RULE_TEXT], [...UPDATES]),
44775
+ ([...RULE_TEXT], [...PACKAGE_UPDATES]),
44776
+ ([...RULE_TEXT], [...PACKAGE_UPDATES]),
44777
+ ([...RULE_TEXT], [...UPDATES]),
44778
+ ([...RULE_TEXT], [...UPDATES]),
44779
+ ([...RULE_TEXT], [...PACKAGE_UPDATES]),
44780
+ [...RULE_TEXT],
44781
+ [...RULE_TEXT],
44782
+ [...RULE_TEXT],
44783
+ [...RULE_TEXT],
44784
+ [...RULE_TEXT],
44785
+ [...RULE_TEXT],
44786
+ [...RULE_TEXT],
44787
+ [...RULE_TEXT],
44788
+ [...RULE_TEXT],
44789
+ [...RULE_TEXT],
44790
+ [...RULE_TEXT],
44791
+ [...RULE_TEXT],
44792
+ [...RULE_TEXT],
44793
+ [...RULE_TEXT],
44794
+ [...RULE_TEXT],
44795
+ [...RULE_TEXT],
44796
+ [...RULE_TEXT],
44797
+ [...RULE_TEXT],
44798
+ [...RULE_TEXT],
44799
+ [...RULE_TEXT],
44800
+ [...RULE_TEXT],
44801
+ [...RULE_TEXT],
44802
+ [...RULE_TEXT],
44803
+ [...RULE_TEXT],
44804
+ ...STATE_SUMMARY_VARS
44805
+ ];
44450
44806
  /**
44451
44807
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
44452
44808
  *
@@ -44941,7 +45297,7 @@ var AdminUIAddon = class extends BaseAddon {
44941
45297
  capability: adminUiCapability,
44942
45298
  provider: {
44943
45299
  getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
44944
- getVersion: async () => ({ version: "1.2.271" })
45300
+ getVersion: async () => ({ version: "1.2.272" })
44945
45301
  }
44946
45302
  }];
44947
45303
  }