@camstack/addon-osd-manager 0.1.20 → 0.1.21

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 (18) hide show
  1. package/dist/{MotionZonesSettings-Dhh1AqWY.mjs → MotionZonesSettings-C1tuU9vA.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-CPABuSH1.mjs → PrivacyMaskSettings-BfYwmnx-.mjs} +4 -4
  3. package/dist/{SceneMonitorEditor-CyVjkJI2.mjs → SceneMonitorEditor-Fui6aPeX.mjs} +3 -3
  4. package/dist/_stub.js +11 -11
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-5jby0ZM9.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-CUYUIYix.mjs} +4 -4
  6. package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BhABwRxy.mjs +26 -0
  7. package/dist/{hostInit-5GIsHCyh.mjs → hostInit-wPjKQ8mT.mjs} +3 -3
  8. package/dist/index.js +222 -33
  9. package/dist/index.mjs +222 -33
  10. package/dist/{player-overlays-A11g0xRn.mjs → player-overlays-B_C4YyEi.mjs} +1 -1
  11. package/dist/remoteEntry.js +1 -1
  12. package/dist/{responsive-B_W10135.mjs → responsive-BzwsIYSh.mjs} +1 -1
  13. package/dist/{square-BqxtsJJ4.mjs → square-X_zDrz0l.mjs} +1 -1
  14. package/dist/{trash-2-xxP-WwG0.mjs → trash-2-BldQMEFN.mjs} +1 -1
  15. package/dist/{use-device-snapshot-B6sowK2s.mjs → use-device-snapshot-Bxo1wH26.mjs} +1 -1
  16. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-0ziNXHDT.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-DZH4YPzH.mjs} +1 -1
  17. package/package.json +1 -1
  18. package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DO3S4jGF.mjs +0 -26
package/dist/index.js CHANGED
@@ -5804,6 +5804,13 @@ var BaseAddon = class {
5804
5804
  _readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
5805
5805
  /** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
5806
5806
  _registeredCapNames = [];
5807
+ /**
5808
+ * True only after `readAddonStore` actually answered. Constructor
5809
+ * defaults look like stored config when the store is down — a forked
5810
+ * addon that auto-starts from those defaults (cloudflare-tunnel quick
5811
+ * mode, 2026-08-25) is not "the operator chose this".
5812
+ */
5813
+ settingsStoreReady = false;
5807
5814
  /** Default config values. Provided via constructor. */
5808
5815
  defaults;
5809
5816
  constructor(defaults) {
@@ -6204,7 +6211,9 @@ var BaseAddon = class {
6204
6211
  ];
6205
6212
  let lastErr;
6206
6213
  for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
6207
- return await settings.readAddonStore() ?? {};
6214
+ const stored = await settings.readAddonStore() ?? {};
6215
+ this.settingsStoreReady = true;
6216
+ return stored;
6208
6217
  } catch (err) {
6209
6218
  lastErr = err;
6210
6219
  const msg = err instanceof Error ? err.message : String(err);
@@ -6212,6 +6221,7 @@ var BaseAddon = class {
6212
6221
  if (attempt === delaysMs.length) break;
6213
6222
  await new Promise((r) => setTimeout(r, delaysMs[attempt]));
6214
6223
  }
6224
+ this.settingsStoreReady = false;
6215
6225
  this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
6216
6226
  return {};
6217
6227
  }
@@ -8187,6 +8197,12 @@ var ModelVariantGroupSchema = object({
8187
8197
  */
8188
8198
  resolution: number().int().positive().optional()
8189
8199
  });
8200
+ var ModelProviderIdSchema = _enum([
8201
+ "camstack",
8202
+ "frigate",
8203
+ "scrypted",
8204
+ "custom"
8205
+ ]);
8190
8206
  var ModelCatalogEntrySchema = object({
8191
8207
  id: string(),
8192
8208
  name: string(),
@@ -8284,6 +8300,12 @@ var ModelCatalogEntrySchema = object({
8284
8300
  */
8285
8301
  group: ModelVariantGroupSchema.optional(),
8286
8302
  /**
8303
+ * Catalog source for the pipeline stepper's provider-first picker. Absent on
8304
+ * built-in CamStack entries (treated as `camstack`) and on registry rows
8305
+ * persisted before this field existed (`inferModelProvider` fills those).
8306
+ */
8307
+ provider: ModelProviderIdSchema.optional(),
8308
+ /**
8287
8309
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8288
8310
  * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8289
8311
  * labels already ARE the CamStack macros (Scrypted identity map).
@@ -12884,6 +12906,27 @@ var LinkedDeviceSchema = object({
12884
12906
  features: array(string()),
12885
12907
  producesTrackedEvents: boolean().optional()
12886
12908
  });
12909
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
12910
+ * The batch answer needs the tag; the single-device answer already has it
12911
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
12912
+ var LinkedDevicesForDeviceSchema = object({
12913
+ deviceId: number(),
12914
+ mode: LinkedDevicesModeSchema,
12915
+ devices: array(LinkedDeviceSchema)
12916
+ });
12917
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
12918
+ * `getAllBindings` all answer in. Declared once: three copies of the same
12919
+ * object literal is exactly how the three drift apart. */
12920
+ var DeviceBindingsForDeviceSchema = object({
12921
+ deviceId: number(),
12922
+ entries: array(object({
12923
+ capName: string(),
12924
+ kind: _enum(["native", "wrapped"]),
12925
+ providerAddonId: string(),
12926
+ providerNodeId: string(),
12927
+ nativeAddonId: string()
12928
+ }))
12929
+ });
12887
12930
  var SavedDeviceRowSchema = object({
12888
12931
  /** Numeric id reserved at allocateDeviceId time. */
12889
12932
  id: number(),
@@ -13246,7 +13289,21 @@ var deviceManagerCapability = {
13246
13289
  projection: _enum(["full", "slim"]).optional(),
13247
13290
  /** Return only camera devices. Filtering server-side instead of
13248
13291
  * shipping 293 rows to find 12. */
13249
- isCamera: boolean().optional()
13292
+ isCamera: boolean().optional(),
13293
+ /**
13294
+ * Return only these device ids. For the caller that already KNOWS the
13295
+ * handful it wants and needs a field the id-bearing answer does not
13296
+ * carry — the viewer's linked-devices panel joins `type` and `online`
13297
+ * onto ~8 linked ids and, unfiltered, dragged the fleet across to do
13298
+ * it: 433 KB slim / 958 KB full for 967 devices, on a query that
13299
+ * refetches on the reconcile interval, on a phone.
13300
+ *
13301
+ * Safe to send at a hub that predates it: Zod STRIPS unknown input
13302
+ * keys rather than rejecting them (verified against the live hub
13303
+ * 2026-08-25 — 967 rows came back), so an old hub answers exactly what
13304
+ * it answers today and the caller filters as it already does.
13305
+ */
13306
+ deviceIds: array(number()).optional()
13250
13307
  }), array(DeviceInfoSchema)),
13251
13308
  /** Get a single device by numeric deviceId. */
13252
13309
  getDevice: method(object({ deviceId: number() }), DeviceInfoSchema.nullable()),
@@ -13265,6 +13322,23 @@ var deviceManagerCapability = {
13265
13322
  mode: LinkedDevicesModeSchema,
13266
13323
  devices: array(LinkedDeviceSchema)
13267
13324
  })),
13325
+ /**
13326
+ * `getLinkedDevices` for MANY cameras, in one call.
13327
+ *
13328
+ * Not a convenience wrapper — a cost fix. Resolving one camera's linked set
13329
+ * needs the whole fleet as candidates (children ∪ same-location), so the
13330
+ * single-device path runs a full `listAll` per call. Asked per camera that
13331
+ * is N full-fleet sweeps of device-manager's event loop, and they do not
13332
+ * overlap: measured on the live hub 2026-08-25, 30 concurrent
13333
+ * `getLinkedDevices` took 4110 ms wall (median 4060 ms each) to return
13334
+ * 7260 bytes in total. The batch takes ONE sweep and one settings read per
13335
+ * camera.
13336
+ *
13337
+ * A device id that resolves to nothing still gets a row (`devices: []`) —
13338
+ * a caller that asked for thirty and got twenty-eight cannot tell which two
13339
+ * are missing, or that any are.
13340
+ */
13341
+ getLinkedDevicesBatch: method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)),
13268
13342
  /** Get stream sources for a camera device. */
13269
13343
  getStreamSources: method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)),
13270
13344
  /** Get config entries (key + value + description) for a device. */
@@ -13322,16 +13396,22 @@ var deviceManagerCapability = {
13322
13396
  * currently-active provider (native or wrapper) + the underlying native
13323
13397
  * addon id, so consumers can decide routing without re-running discovery.
13324
13398
  */
13325
- getBindings: method(object({ deviceId: number() }), object({
13326
- deviceId: number(),
13327
- entries: array(object({
13328
- capName: string(),
13329
- kind: _enum(["native", "wrapped"]),
13330
- providerAddonId: string(),
13331
- providerNodeId: string(),
13332
- nativeAddonId: string()
13333
- }))
13334
- })),
13399
+ getBindings: method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema),
13400
+ /**
13401
+ * `getBindings` for a NAMED set of devices, in one call.
13402
+ *
13403
+ * Between `getBindings` (one device) and `getAllBindings` (all 988) there
13404
+ * was nothing, so a caller that needs seventy-five either pays
13405
+ * seventy-five round-trips or drags the whole fleet across. Measured on
13406
+ * the live hub 2026-08-25: 75 concurrent `getBindings` = 1211 ms / 118 KB,
13407
+ * `getAllBindings({})` = 511 ms / 679 KB. Neither is the right answer to
13408
+ * "these seventy-five".
13409
+ *
13410
+ * Same resolver, same routing rules, same per-device shape as
13411
+ * `getBindings`; ids are deduped and a device with no bindings answers
13412
+ * `entries: []` rather than dropping out.
13413
+ */
13414
+ getBindingsBatch: method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)),
13335
13415
  /**
13336
13416
  * Return the binding map for every device known to the hub. Used by
13337
13417
  * `SystemManager` warm-boot: a single round-trip resolves the
@@ -13340,16 +13420,7 @@ var deviceManagerCapability = {
13340
13420
  * device add/remove) — clients invalidate via the
13341
13421
  * `capability.binding-changed` event.
13342
13422
  */
13343
- getAllBindings: method(object({}), array(object({
13344
- deviceId: number(),
13345
- entries: array(object({
13346
- capName: string(),
13347
- kind: _enum(["native", "wrapped"]),
13348
- providerAddonId: string(),
13349
- providerNodeId: string(),
13350
- nativeAddonId: string()
13351
- }))
13352
- }))),
13423
+ getAllBindings: method(object({}), array(DeviceBindingsForDeviceSchema)),
13353
13424
  /**
13354
13425
  * Activate (or deactivate) a wrapper addon for a (device, cap) pair.
13355
13426
  * Persists the binding via ctx.settings. active=false clears the wrapper
@@ -16237,12 +16308,15 @@ var NcOccupancyConditionSchema = object({
16237
16308
  * there is no second switch that can disagree with the first and every rule
16238
16309
  * authored before the decision migrates for free (`audioModeOf`):
16239
16310
  *
16240
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
16241
- * classifier labels with one of them. No window, no percentage:
16242
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
16243
- * `throttle` cooldown is the only brake. The per-label confidence floor is
16244
- * the analyzer's (`classificationMinScore`, per device) a label only
16245
- * reaches this condition if the classifier was already confident enough.
16311
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
16312
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
16313
+ * `hitPercent` and `samplingSeconds` are still ignored a percentage of
16314
+ * frames is the wrong question for a classifier that labels 1–3 frames
16315
+ * per episode. The count window is the brake that drops a single-frame
16316
+ * false positive; the rule's own `throttle` cooldown is the other. The
16317
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
16318
+ * per device) — a label only reaches this condition if the classifier was
16319
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
16246
16320
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
16247
16321
  * the condition: at least `hitPercent`% of the samples over
16248
16322
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -16269,14 +16343,22 @@ var NcOccupancyConditionSchema = object({
16269
16343
  * an operator who typed `dog` mean the same thing.
16270
16344
  */
16271
16345
  var NcAudioConditionSchema = object({
16272
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
16346
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
16273
16347
  labels: array(string().min(1)).min(1).optional(),
16274
16348
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
16275
16349
  dbThreshold: number().min(-96).max(0).optional(),
16276
16350
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
16277
16351
  hitPercent: number().int().min(1).max(100).default(60),
16278
16352
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
16279
- samplingSeconds: number().int().min(1).max(300).default(10)
16353
+ samplingSeconds: number().int().min(1).max(300).default(10),
16354
+ /**
16355
+ * LABEL MODE: how many labelled frames must land inside
16356
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
16357
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
16358
+ */
16359
+ confirmHits: number().int().min(1).max(20).optional(),
16360
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
16361
+ confirmWindowSec: number().int().min(1).max(60).optional()
16280
16362
  });
16281
16363
  /**
16282
16364
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -19201,6 +19283,46 @@ var RecentTracksPageSchema = object({
19201
19283
  /** Cursor for the next page, or null when this page is the last. */
19202
19284
  nextCursor: string().nullable()
19203
19285
  });
19286
+ var LIST_GROUPS_DEFAULT_LIMIT = 40;
19287
+ var LIST_GROUPS_MAX_LIMIT = 100;
19288
+ var AnalyticsGroupRecordSchema = object({
19289
+ id: string(),
19290
+ deviceId: number().int(),
19291
+ openedAt: number().int(),
19292
+ closedAt: number().int(),
19293
+ timestamp: number().int(),
19294
+ memberCount: number().int(),
19295
+ memberTrackIds: array(string()).readonly(),
19296
+ className: string(),
19297
+ classes: array(string()).readonly(),
19298
+ /** Relative event-media path, or null when the group has no picture yet. */
19299
+ mediaUrl: string().nullable(),
19300
+ singleton: boolean()
19301
+ });
19302
+ var AnalyticsGroupMemberSchema = object({
19303
+ trackId: string(),
19304
+ deviceId: number().int(),
19305
+ className: string(),
19306
+ firstSeen: number().int(),
19307
+ lastSeen: number().int(),
19308
+ mediaUrl: string().nullable()
19309
+ });
19310
+ var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19311
+ var ListGroupsQueryInput = object({
19312
+ /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19313
+ deviceIds: array(number()),
19314
+ /** Window lower bound on `closedAt` (inclusive). */
19315
+ since: number().optional(),
19316
+ /** Window upper bound on `openedAt` (inclusive). */
19317
+ until: number().optional(),
19318
+ limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19319
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
19320
+ cursor: string().optional()
19321
+ });
19322
+ var ListGroupsPageSchema = object({
19323
+ groups: array(AnalyticsGroupRecordSchema).readonly(),
19324
+ nextCursor: string().nullable()
19325
+ });
19204
19326
  var KeyEventQueryInput = object({
19205
19327
  deviceId: number(),
19206
19328
  /** Window lower bound (track firstSeen ≥ since). */
@@ -19276,7 +19398,9 @@ var TrackCascadeCountsSchema = object({
19276
19398
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19277
19399
  plates: number().int(),
19278
19400
  /** Per-track CLIP search vectors removed (best-effort). */
19279
- embeddings: number().int()
19401
+ embeddings: number().int(),
19402
+ /** Group membership + group rows removed with their last member (best-effort). */
19403
+ groups: number().int()
19280
19404
  });
19281
19405
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19282
19406
  var DiskReconcileCountsSchema = object({
@@ -19448,6 +19572,16 @@ var pipelineAnalyticsCapability = {
19448
19572
  * are not included (same contract as `listTracks`).
19449
19573
  */
19450
19574
  listRecentTracks: method(RecentTracksQueryInput, RecentTracksPageSchema),
19575
+ /**
19576
+ * Batched co-moving group listing — the Groups feed. Same merge/cursor
19577
+ * contract as {@link listRecentTracks}. A group is a sealed partition of
19578
+ * one session; `getGroup` is the detail with members.
19579
+ */
19580
+ listGroups: method(ListGroupsQueryInput, ListGroupsPageSchema),
19581
+ getGroup: method(object({
19582
+ deviceId: number(),
19583
+ groupId: string().min(1)
19584
+ }), AnalyticsGroupDetailSchema.nullable()),
19451
19585
  clearTracks: method(object({ deviceId: number() }), _void(), {
19452
19586
  kind: "mutation",
19453
19587
  auth: "admin"
@@ -20133,7 +20267,8 @@ var PipelineModelOptionSchema = object({
20133
20267
  sizeMB: number()
20134
20268
  })),
20135
20269
  group: ModelVariantGroupSchema.optional(),
20136
- legacy: boolean().optional()
20270
+ legacy: boolean().optional(),
20271
+ provider: ModelProviderIdSchema.optional()
20137
20272
  });
20138
20273
  var ConfigFieldBridge = custom();
20139
20274
  var PipelineAddonSchemaSchema = object({
@@ -29971,7 +30106,12 @@ var PlateInfoSchema = object({
29971
30106
  plateBbox: BoundingBoxSchema.optional(),
29972
30107
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
29973
30108
  keyFrameMediaKey: string().optional(),
29974
- base64: string().optional()
30109
+ base64: string().optional(),
30110
+ /**
30111
+ * Same crop as a data-plane URL. `getPlateByTrack` returns this and
30112
+ * never inlines JPEG; `listPlates` still inlines for the admin-ui.
30113
+ */
30114
+ cropUrl: string().optional()
29975
30115
  });
29976
30116
  var MediaFileLiteSchema = object({
29977
30117
  key: string(),
@@ -35001,6 +35141,12 @@ Object.freeze({
35001
35141
  addonId: null,
35002
35142
  access: "view"
35003
35143
  },
35144
+ "deviceManager.getBindingsBatch": {
35145
+ capName: "device-manager",
35146
+ capScope: "system",
35147
+ addonId: null,
35148
+ access: "view"
35149
+ },
35004
35150
  "deviceManager.getChildren": {
35005
35151
  capName: "device-manager",
35006
35152
  capScope: "system",
@@ -35061,6 +35207,12 @@ Object.freeze({
35061
35207
  addonId: null,
35062
35208
  access: "view"
35063
35209
  },
35210
+ "deviceManager.getLinkedDevicesBatch": {
35211
+ capName: "device-manager",
35212
+ capScope: "system",
35213
+ addonId: null,
35214
+ access: "view"
35215
+ },
35064
35216
  "deviceManager.getRoleDisplayDefaults": {
35065
35217
  capName: "device-manager",
35066
35218
  capScope: "system",
@@ -36831,6 +36983,12 @@ Object.freeze({
36831
36983
  addonId: null,
36832
36984
  access: "view"
36833
36985
  },
36986
+ "pipelineAnalytics.getGroup": {
36987
+ capName: "pipeline-analytics",
36988
+ capScope: "device",
36989
+ addonId: null,
36990
+ access: "view"
36991
+ },
36834
36992
  "pipelineAnalytics.getKeyEvents": {
36835
36993
  capName: "pipeline-analytics",
36836
36994
  capScope: "device",
@@ -36915,6 +37073,12 @@ Object.freeze({
36915
37073
  addonId: null,
36916
37074
  access: "view"
36917
37075
  },
37076
+ "pipelineAnalytics.listGroups": {
37077
+ capName: "pipeline-analytics",
37078
+ capScope: "device",
37079
+ addonId: null,
37080
+ access: "view"
37081
+ },
36918
37082
  "pipelineAnalytics.listOpsLog": {
36919
37083
  capName: "pipeline-analytics",
36920
37084
  capScope: "device",
@@ -39696,6 +39860,11 @@ Object.freeze({
39696
39860
  form: "single",
39697
39861
  optional: false
39698
39862
  }],
39863
+ "deviceManager.getBindingsBatch": [{
39864
+ name: "deviceIds",
39865
+ form: "array",
39866
+ optional: false
39867
+ }],
39699
39868
  "deviceManager.getChildren": [{
39700
39869
  name: "parentDeviceId",
39701
39870
  form: "single",
@@ -39741,6 +39910,11 @@ Object.freeze({
39741
39910
  form: "single",
39742
39911
  optional: false
39743
39912
  }],
39913
+ "deviceManager.getLinkedDevicesBatch": [{
39914
+ name: "deviceIds",
39915
+ form: "array",
39916
+ optional: false
39917
+ }],
39744
39918
  "deviceManager.getSettingsSchema": [{
39745
39919
  name: "deviceId",
39746
39920
  form: "single",
@@ -39761,6 +39935,11 @@ Object.freeze({
39761
39935
  form: "single",
39762
39936
  optional: false
39763
39937
  }],
39938
+ "deviceManager.listAll": [{
39939
+ name: "deviceIds",
39940
+ form: "array",
39941
+ optional: true
39942
+ }],
39764
39943
  "deviceManager.loadConfig": [{
39765
39944
  name: "deviceId",
39766
39945
  form: "single",
@@ -40334,6 +40513,11 @@ Object.freeze({
40334
40513
  form: "single",
40335
40514
  optional: false
40336
40515
  }],
40516
+ "pipelineAnalytics.getGroup": [{
40517
+ name: "deviceId",
40518
+ form: "single",
40519
+ optional: false
40520
+ }],
40337
40521
  "pipelineAnalytics.getKeyEvents": [{
40338
40522
  name: "deviceId",
40339
40523
  form: "single",
@@ -40389,6 +40573,11 @@ Object.freeze({
40389
40573
  form: "array",
40390
40574
  optional: false
40391
40575
  }],
40576
+ "pipelineAnalytics.listGroups": [{
40577
+ name: "deviceIds",
40578
+ form: "array",
40579
+ optional: false
40580
+ }],
40392
40581
  "pipelineAnalytics.listOpsLog": [{
40393
40582
  name: "deviceId",
40394
40583
  form: "single",