@camstack/addon-post-analysis 0.1.17 → 0.1.19

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 (42) hide show
  1. package/dist/embedding-encoder/index.js +1 -1
  2. package/dist/embedding-encoder/index.mjs +1 -1
  3. package/dist/enrichment-engine/index.js +1 -1
  4. package/dist/enrichment-engine/index.mjs +1 -1
  5. package/dist/{index-Dbx13pc7.js → index-BFbwYH1P.js} +436 -53
  6. package/dist/index-BFbwYH1P.js.map +1 -0
  7. package/dist/{index-CGAj-pkn.mjs → index-BrTlzsrE.mjs} +436 -53
  8. package/dist/index-BrTlzsrE.mjs.map +1 -0
  9. package/dist/pipeline-analytics/@mf-types.zip +0 -0
  10. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-NjF4kxzW.mjs +19 -0
  11. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-7HAAnpQu.mjs +18 -0
  12. package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-D-USVuHq.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-BZTB2scQ.mjs} +2 -1
  13. package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-qQCPW8pT.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-CJO5YKGV.mjs} +1 -1
  14. package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-Bv9bYz9E.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-B0h0AGOH.mjs} +1 -1
  15. package/dist/pipeline-analytics/_stub.js +2 -2
  16. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Djvv92Kv.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-kZBmgzMg.mjs} +6 -6
  17. package/dist/pipeline-analytics/{client-DHmQcIWy.mjs → client-BlxIUpgf.mjs} +2 -2
  18. package/dist/pipeline-analytics/{hostInit-cznE5sde.mjs → hostInit-qBB1Thhi.mjs} +12 -12
  19. package/dist/pipeline-analytics/{index-CHnXxMRA.mjs → index-BoL0rgZt.mjs} +1 -1
  20. package/dist/pipeline-analytics/{index-DicaGC31.mjs → index-CR1aiZDH.mjs} +1 -1
  21. package/dist/pipeline-analytics/{index-Crs1D0Uu.mjs → index-DlhiA9R0.mjs} +1 -1
  22. package/dist/pipeline-analytics/{index-gpelkpEE.mjs → index-DtdgkNgf.mjs} +1 -1
  23. package/dist/pipeline-analytics/{index-BA65ZJOW.mjs → index-Dw6Q30NI.mjs} +2 -2
  24. package/dist/pipeline-analytics/{index-BCEx31Mh.mjs → index-Dy2V7VOm.mjs} +3808 -3277
  25. package/dist/pipeline-analytics/index-i47purqY.mjs +37880 -0
  26. package/dist/pipeline-analytics/index.js +1 -1
  27. package/dist/pipeline-analytics/index.mjs +1 -1
  28. package/dist/pipeline-analytics/{jsx-runtime-Wcfyyyt4.mjs → jsx-runtime-Dlbl3gpr.mjs} +1 -1
  29. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  30. package/dist/pipeline-analytics/{schemas-ChN4Ih0h.mjs → schemas-ClCuS4qa.mjs} +151 -141
  31. package/dist/recording/index.js +2 -2
  32. package/dist/recording/index.mjs +2 -2
  33. package/dist/{recording-coordinator-b-7Ast8s.js → recording-coordinator-BoGr5moz.js} +2 -2
  34. package/dist/{recording-coordinator-b-7Ast8s.js.map → recording-coordinator-BoGr5moz.js.map} +1 -1
  35. package/dist/{recording-coordinator-BjWd7HjD.mjs → recording-coordinator-CsYH9LqF.mjs} +2 -2
  36. package/dist/{recording-coordinator-BjWd7HjD.mjs.map → recording-coordinator-CsYH9LqF.mjs.map} +1 -1
  37. package/package.json +1 -1
  38. package/dist/index-CGAj-pkn.mjs.map +0 -1
  39. package/dist/index-Dbx13pc7.js.map +0 -1
  40. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-d8PmLbO2.mjs +0 -19
  41. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BcWYbuKp.mjs +0 -18
  42. package/dist/pipeline-analytics/index-gbflFMEY.mjs +0 -36403
@@ -4778,6 +4778,16 @@ function record(keyType, valueType, params) {
4778
4778
  ...normalizeParams(params)
4779
4779
  });
4780
4780
  }
4781
+ function partialRecord(keyType, valueType, params) {
4782
+ const k = clone(keyType);
4783
+ k._zod.values = void 0;
4784
+ return new ZodRecord({
4785
+ type: "record",
4786
+ keyType: k,
4787
+ valueType,
4788
+ ...normalizeParams(params)
4789
+ });
4790
+ }
4781
4791
  const ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
4782
4792
  $ZodEnum.init(inst, def);
4783
4793
  ZodType.init(inst, def);
@@ -5054,6 +5064,37 @@ function _instanceof(cls, params = {}) {
5054
5064
  };
5055
5065
  return inst;
5056
5066
  }
5067
+ const wiringProbeKindSchema = _enum(["singleton", "device", "widget"]);
5068
+ const wiringProbeResultSchema = object({
5069
+ capName: string(),
5070
+ kind: wiringProbeKindSchema,
5071
+ deviceId: number().optional(),
5072
+ reachable: boolean(),
5073
+ latencyMs: number(),
5074
+ error: string().optional()
5075
+ });
5076
+ const wiringAddonHealthSchema = object({
5077
+ addonId: string(),
5078
+ caps: array(wiringProbeResultSchema).readonly(),
5079
+ widgets: array(wiringProbeResultSchema).readonly()
5080
+ });
5081
+ const wiringNodeHealthSchema = object({
5082
+ nodeId: string(),
5083
+ addons: array(wiringAddonHealthSchema).readonly()
5084
+ });
5085
+ object({
5086
+ /** True only when every probed target is reachable. */
5087
+ ok: boolean(),
5088
+ /** True when at least one target is unreachable. */
5089
+ degraded: boolean(),
5090
+ checkedAt: string(),
5091
+ nodes: array(wiringNodeHealthSchema).readonly(),
5092
+ summary: object({
5093
+ total: number(),
5094
+ reachable: number(),
5095
+ unreachable: number()
5096
+ })
5097
+ });
5057
5098
  const MODEL_FORMATS = ["onnx", "coreml", "openvino", "tflite", "pt"];
5058
5099
  const WELL_KNOWN_TABS = [
5059
5100
  { id: "overview", label: "Overview", icon: "layout-dashboard", order: -10 },
@@ -6583,7 +6624,7 @@ const SpatialDetectionSchema = object({
6583
6624
  bbox: BoundingBoxSchema
6584
6625
  });
6585
6626
  const AudioChunkInputSchema = object({
6586
- data: _instanceof(Float32Array),
6627
+ data: _instanceof(Uint8Array),
6587
6628
  sampleRate: number(),
6588
6629
  channels: number(),
6589
6630
  timestamp: number(),
@@ -7254,7 +7295,23 @@ const RunnerCameraConfigSchema = object({
7254
7295
  * whenever its `zones` device-state slice changes, so the runner's
7255
7296
  * copy stays in sync. Empty array → no zone filtering.
7256
7297
  */
7257
- zones: array(ZoneSchema).readonly().default([])
7298
+ zones: array(ZoneSchema).readonly().default([]),
7299
+ /**
7300
+ * When true (default) and the camera's `motionSources` contains only
7301
+ * `'onboard'`, the runner dynamically opens the same WASM frame-diff
7302
+ * motion-frames subscription on each `MotionOnMotionChanged
7303
+ * source:'onboard'` event and tears it down after `motionCooldownMs`.
7304
+ * This causes `runMotionAnalysis` to emit `MotionZonesRaw` /
7305
+ * `MotionAnalysis` during active-motion windows without the
7306
+ * substream being held open continuously.
7307
+ *
7308
+ * Set to `false` to disable the dynamic analyzer for this camera
7309
+ * (e.g. very low-bandwidth links where the extra substream is
7310
+ * undesirable). Has no effect when `motionSources` already includes
7311
+ * `'analyzer'` — the analyzer runs continuously in that case and
7312
+ * this gate is bypassed.
7313
+ */
7314
+ onboardMotionDrivesAnalyzer: boolean().default(true)
7258
7315
  });
7259
7316
  const RunnerLocalLoadSchema = object({
7260
7317
  /** Moleculer node id of this runner instance. */
@@ -7391,22 +7448,68 @@ MotionTriggerStatusSchema.extend({
7391
7448
  }) }
7392
7449
  }
7393
7450
  });
7451
+ const MaskPointSchema = object({
7452
+ x: number(),
7453
+ y: number()
7454
+ });
7455
+ const MaskRectShapeSchema = object({
7456
+ kind: literal("rect"),
7457
+ x: number(),
7458
+ y: number(),
7459
+ width: number(),
7460
+ height: number()
7461
+ });
7462
+ const MaskPolygonShapeSchema = object({
7463
+ kind: literal("polygon"),
7464
+ points: array(MaskPointSchema)
7465
+ });
7466
+ const MaskGridShapeSchema = object({
7467
+ kind: literal("grid"),
7468
+ gridWidth: number(),
7469
+ gridHeight: number(),
7470
+ cells: array(boolean())
7471
+ });
7472
+ const MaskLineShapeSchema = object({
7473
+ kind: literal("line"),
7474
+ points: array(MaskPointSchema)
7475
+ });
7476
+ discriminatedUnion("kind", [
7477
+ MaskRectShapeSchema,
7478
+ MaskPolygonShapeSchema,
7479
+ MaskGridShapeSchema,
7480
+ MaskLineShapeSchema
7481
+ ]);
7482
+ const MaskShapeKindSchema = _enum(["rect", "polygon", "grid", "line"]);
7483
+ const MaskPolygonVerticesSchema = object({
7484
+ min: number(),
7485
+ max: number()
7486
+ });
7487
+ const MaskGridDimsSchema = object({
7488
+ width: number(),
7489
+ height: number()
7490
+ });
7491
+ const MotionZoneRegionSchema = object({
7492
+ id: number(),
7493
+ enabled: boolean(),
7494
+ shape: MaskGridShapeSchema
7495
+ });
7394
7496
  object({
7395
7497
  enabled: boolean(),
7396
7498
  sensitivity: number(),
7397
- /** Row-major active-cell grid. Length = gridWidth*gridHeight (see getOptions). */
7398
- cells: array(boolean()),
7499
+ /** Grid region(s). Today exactly one `grid` shape. */
7500
+ regions: array(MotionZoneRegionSchema),
7399
7501
  lastFetchedAt: number()
7400
7502
  });
7401
7503
  const MotionZoneOptionsSchema = object({
7402
- gridWidth: number(),
7403
- gridHeight: number(),
7504
+ maxRegions: number(),
7505
+ supportedShapes: array(MaskShapeKindSchema),
7506
+ grid: MaskGridDimsSchema,
7404
7507
  sensitivity: object({ min: number(), max: number(), step: number() })
7405
7508
  });
7406
7509
  const MotionZonePatchSchema = object({
7407
7510
  enabled: boolean().optional(),
7408
7511
  sensitivity: number().optional(),
7409
- cells: array(boolean()).optional()
7512
+ regions: array(MotionZoneRegionSchema).optional()
7410
7513
  });
7411
7514
  ({
7412
7515
  deviceTypes: [DeviceType.Camera],
@@ -7419,6 +7522,102 @@ const MotionZonePatchSchema = object({
7419
7522
  )
7420
7523
  }
7421
7524
  });
7525
+ const NativeObjectClassEnum = _enum([
7526
+ "person",
7527
+ "vehicle",
7528
+ "animal",
7529
+ "face",
7530
+ "package",
7531
+ "other"
7532
+ ]);
7533
+ const NativeDetectionSchema = object({
7534
+ class: NativeObjectClassEnum,
7535
+ timestamp: number(),
7536
+ /** Firmware-provided confidence [0..1]. Reolink pushes don't carry it → undefined. */
7537
+ confidence: number().min(0).max(1).optional()
7538
+ });
7539
+ const NativeObjectDetectionStatusSchema = object({
7540
+ /**
7541
+ * Last observed instance per class. Missing entries mean the class
7542
+ * is supported but nothing has been seen since the provider started.
7543
+ *
7544
+ * MUST be a partial record: providers seed an empty `{}` on cold-start
7545
+ * and write one class at a time as detections arrive. In Zod 4
7546
+ * `z.record(enum, …)` is EXHAUSTIVE (requires every enum key), so a
7547
+ * partial write throws "expected object, received undefined" for every
7548
+ * unseen class. `z.partialRecord` keeps the enum-key narrowing while
7549
+ * allowing the sparse shape the providers actually write.
7550
+ */
7551
+ lastByClass: partialRecord(NativeObjectClassEnum, NativeDetectionSchema.nullable()),
7552
+ /** Classes the firmware is capable of detecting — enumerated at device register. */
7553
+ supportedClasses: array(NativeObjectClassEnum).readonly(),
7554
+ /**
7555
+ * Whether forwarding of onboard AI detections is enabled for this device.
7556
+ * Default true (on cold-start) — detections flow unconditionally before
7557
+ * the toggle is saved, so defaulting true preserves existing behaviour.
7558
+ */
7559
+ enabled: boolean()
7560
+ });
7561
+ NativeObjectDetectionStatusSchema.extend({
7562
+ /** Required by createRuntimeStateBridge — epoch ms of last refresh. */
7563
+ lastFetchedAt: number()
7564
+ });
7565
+ ({
7566
+ deviceTypes: [DeviceType.Camera],
7567
+ methods: {
7568
+ setEnabled: method(
7569
+ object({ deviceId: number(), enabled: boolean() }),
7570
+ _void(),
7571
+ { kind: "mutation", auth: "admin" }
7572
+ )
7573
+ },
7574
+ events: {
7575
+ onDetected: { data: object({
7576
+ deviceId: number(),
7577
+ detection: NativeDetectionSchema
7578
+ }) }
7579
+ }
7580
+ });
7581
+ const PrivacyMaskShapeSchema = discriminatedUnion("kind", [
7582
+ MaskRectShapeSchema,
7583
+ MaskPolygonShapeSchema
7584
+ ]);
7585
+ const PrivacyMaskRegionSchema = object({
7586
+ /** Slot id, 0-based. Stable across read/write. */
7587
+ id: number(),
7588
+ /** Whether this zone is active (blanked out by the camera). */
7589
+ enabled: boolean(),
7590
+ shape: PrivacyMaskShapeSchema
7591
+ });
7592
+ object({
7593
+ enabled: boolean(),
7594
+ /** Active zones (normalized 0..1). Length ≤ maxRegions. */
7595
+ regions: array(PrivacyMaskRegionSchema),
7596
+ lastFetchedAt: number()
7597
+ });
7598
+ const PrivacyMaskOptionsSchema = object({
7599
+ /** Maximum number of supported zones. */
7600
+ maxRegions: number(),
7601
+ /** Shape kinds this camera accepts — Reolink: ['rect']; Hikvision: ['rect','polygon']. */
7602
+ supportedShapes: array(MaskShapeKindSchema),
7603
+ /** Polygon vertex bounds when 'polygon' is supported (Hikvision: {min:4,max:4}). */
7604
+ polygonVertices: MaskPolygonVerticesSchema.optional()
7605
+ });
7606
+ const PrivacyMaskPatchSchema = object({
7607
+ enabled: boolean().optional(),
7608
+ regions: array(PrivacyMaskRegionSchema).optional()
7609
+ });
7610
+ ({
7611
+ deviceTypes: [DeviceType.Camera],
7612
+ methods: {
7613
+ getOptions: method(object({ deviceId: number() }), PrivacyMaskOptionsSchema),
7614
+ setMask: method(
7615
+ object({ deviceId: number(), patch: PrivacyMaskPatchSchema }),
7616
+ _void(),
7617
+ { kind: "mutation", auth: "admin" }
7618
+ )
7619
+ }
7620
+ });
7422
7621
  const AutotrackTargetTypeSchema = string().describe("Vendor target string (people/vehicle/pet); empty = camera default");
7423
7622
  const PtzAutotrackSettingsSchema = object({
7424
7623
  targetType: AutotrackTargetTypeSchema,
@@ -7948,7 +8147,8 @@ const SettingsUpdateResultSchema = object({
7948
8147
  object({
7949
8148
  addonId: string(),
7950
8149
  nodeId: string().optional(),
7951
- overlay: record(string(), unknown()).optional()
8150
+ overlay: record(string(), unknown()).optional(),
8151
+ cap: string().optional()
7952
8152
  }),
7953
8153
  SettingsSchemaWithValuesSchema.nullable()
7954
8154
  ),
@@ -8679,7 +8879,14 @@ const OauthIntegrationDescriptorSchema = object({
8679
8879
  /** Allowed redirect_uri prefixes. /api/oauth2/authorize rejects any
8680
8880
  * redirect_uri that does not start with one of these. Required —
8681
8881
  * an empty list means the integration can never complete linking. */
8682
- allowedRedirectPrefixes: array(string()).min(1)
8882
+ allowedRedirectPrefixes: array(string()).min(1),
8883
+ /** Optional public origin (no trailing slash) that this integration's
8884
+ * issued codes/tokens should carry as the `hubUrl` claim — typically the
8885
+ * operator-selected external-access endpoint resolved by the addon. When
8886
+ * present, /api/oauth2/authorize bakes THIS into the code instead of the
8887
+ * hub-global `publicHubUrl()`, so a forked exporter addon (which can't set
8888
+ * the hub's env) drives the claim that its cloud Lambda routes back on. */
8889
+ hubUrl: string().optional()
8683
8890
  });
8684
8891
  ({
8685
8892
  methods: {
@@ -9297,7 +9504,20 @@ const WebrtcStreamChoiceSchema = object({
9297
9504
  object({
9298
9505
  deviceId: number().int().nonnegative(),
9299
9506
  target: WebrtcStreamTargetSchema,
9300
- hints: webrtcClientHintsSchema.optional()
9507
+ hints: webrtcClientHintsSchema.optional(),
9508
+ /**
9509
+ * SERVER-INJECTED — NOT a client hint. The hub layer that holds
9510
+ * the tRPC request context (and therefore the client IP) sets
9511
+ * this to `true` when the viewer's source IP is non-LAN
9512
+ * (4G/CGNAT/internet). The broker then forces TURN-relay-only
9513
+ * ICE for the session so a CGNAT client (which can only offer a
9514
+ * relay candidate) gets a clean relay↔relay media path instead
9515
+ * of werift nominating a dead host/hairpin-srflx pair. LAN
9516
+ * clients leave this absent/false and keep the low-latency
9517
+ * direct (host/srflx) path. Clients MUST NOT send this — the
9518
+ * server overwrites it from the request context.
9519
+ */
9520
+ relayOnly: boolean().optional()
9301
9521
  }),
9302
9522
  object({ sessionId: string(), sdpOffer: string() }),
9303
9523
  { kind: "mutation" }
@@ -9320,7 +9540,22 @@ const WebrtcStreamChoiceSchema = object({
9320
9540
  deviceId: number().int().nonnegative(),
9321
9541
  target: WebrtcStreamTargetSchema.optional(),
9322
9542
  sdpOffer: string(),
9323
- sessionId: string().optional()
9543
+ sessionId: string().optional(),
9544
+ /**
9545
+ * Force TURN-relay-only ICE for this session. Two kinds of caller
9546
+ * set it:
9547
+ * - A cloud peer like Alexa's RTCSessionController (reachable
9548
+ * only via TURN, never our host/srflx behind NAT) passes
9549
+ * `true` from its own trusted addon context.
9550
+ * - The hub injects it for browser client-offer viewers from the
9551
+ * request's source IP (non-LAN ⇒ true), exactly as it does for
9552
+ * `createSession`.
9553
+ * A LAN/Tailscale browser doing client-offer passthrough leaves it
9554
+ * absent/false so a direct host pair carries full native quality.
9555
+ * Untrusted browser clients MUST NOT send it — the hub overwrites
9556
+ * it from the request context.
9557
+ */
9558
+ relayOnly: boolean().optional()
9324
9559
  }),
9325
9560
  object({ sessionId: string(), sdpAnswer: string() }),
9326
9561
  { kind: "mutation" }
@@ -9334,6 +9569,46 @@ const WebrtcStreamChoiceSchema = object({
9334
9569
  _void(),
9335
9570
  { kind: "mutation" }
9336
9571
  ),
9572
+ /**
9573
+ * Trickle ICE — add a remote (client) ICE candidate to a live session.
9574
+ * Lets the client send its SDP offer/answer IMMEDIATELY (before ICE
9575
+ * gathering finishes) and deliver candidates as they arrive, so the
9576
+ * connection establishes in ~0s instead of waiting for full gathering.
9577
+ * The dual of `getIceCandidates`. Mirrors Scrypted's signaling.
9578
+ */
9579
+ addIceCandidate: method(
9580
+ object({
9581
+ deviceId: number().int().nonnegative(),
9582
+ sessionId: string(),
9583
+ candidate: string(),
9584
+ sdpMid: string().nullable().optional(),
9585
+ sdpMLineIndex: number().int().nullable().optional()
9586
+ }),
9587
+ _void(),
9588
+ { kind: "mutation" }
9589
+ ),
9590
+ /**
9591
+ * Trickle ICE — poll the server's gathered ICE candidates for a session.
9592
+ * The server answers immediately (no gathering wait) and the client polls
9593
+ * this to receive host/srflx/relay candidates as werift gathers them,
9594
+ * adding each to its PeerConnection. Returns all candidates gathered so
9595
+ * far; the client dedupes. `done` flips true once gathering completes.
9596
+ */
9597
+ getIceCandidates: method(
9598
+ object({
9599
+ deviceId: number().int().nonnegative(),
9600
+ sessionId: string()
9601
+ }),
9602
+ object({
9603
+ candidates: array(object({
9604
+ candidate: string(),
9605
+ sdpMid: string().nullable(),
9606
+ sdpMLineIndex: number().int().nullable()
9607
+ })),
9608
+ done: boolean()
9609
+ }),
9610
+ { kind: "query" }
9611
+ ),
9337
9612
  closeSession: method(
9338
9613
  object({
9339
9614
  deviceId: number().int().nonnegative(),
@@ -11012,6 +11287,9 @@ const recordingEngineCapability = {
11012
11287
  ({
11013
11288
  deviceTypes: [DeviceType.Camera]
11014
11289
  });
11290
+ ({
11291
+ deviceTypes: [DeviceType.Camera]
11292
+ });
11015
11293
  const TrackStateSchema = _enum(["new", "entered", "left", "moving", "idle"]);
11016
11294
  const EventKindSchema = _enum(["motion", "object", "audio"]);
11017
11295
  const TrackPositionSchema = object({
@@ -11845,36 +12123,28 @@ const IntercomStatusSchema = object({
11845
12123
  }) }
11846
12124
  }
11847
12125
  });
11848
- const NativeObjectClassEnum = _enum([
11849
- "person",
11850
- "vehicle",
11851
- "animal",
11852
- "face",
11853
- "package",
11854
- "other"
11855
- ]);
11856
- const NativeDetectionSchema = object({
11857
- class: NativeObjectClassEnum,
11858
- timestamp: number(),
11859
- /** Firmware-provided confidence [0..1]. Reolink pushes don't carry it → undefined. */
11860
- confidence: number().min(0).max(1).optional()
11861
- });
11862
- object({
11863
- /**
11864
- * Last observed instance per class. Undefined entries mean the class
11865
- * is supported but nothing has been seen since the provider started.
11866
- */
11867
- lastByClass: record(NativeObjectClassEnum, NativeDetectionSchema.nullable()),
11868
- /** Classes the firmware is capable of detecting — enumerated at device register. */
11869
- supportedClasses: array(NativeObjectClassEnum).readonly()
12126
+ const CamStreamDescriptorSchema = object({
12127
+ camStreamId: string().min(1),
12128
+ kind: CamStreamKindSchema,
12129
+ url: string().optional(),
12130
+ codec: string().optional(),
12131
+ resolution: CamStreamResolutionSchema.optional(),
12132
+ fps: number().positive().optional(),
12133
+ label: string().optional(),
12134
+ /** Device-level features (e.g. `battery-operated`) — drives broker policy. */
12135
+ deviceFeatures: array(string()).optional(),
12136
+ /** Eligible for automatic profile assignment. Absent = `true`. */
12137
+ autoEligible: boolean().optional(),
12138
+ /** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
12139
+ metadata: record(string(), unknown()).optional()
11870
12140
  });
11871
12141
  ({
11872
12142
  deviceTypes: [DeviceType.Camera],
11873
- events: {
11874
- onDetected: { data: object({
11875
- deviceId: number(),
11876
- detection: NativeDetectionSchema
11877
- }) }
12143
+ methods: {
12144
+ getCatalog: method(
12145
+ object({ deviceId: number().int().nonnegative() }),
12146
+ array(CamStreamDescriptorSchema).readonly()
12147
+ )
11878
12148
  }
11879
12149
  });
11880
12150
  const ModelFormatSchema = _enum(MODEL_FORMATS);
@@ -12742,6 +13012,18 @@ const TopologyProcessSchema = object({
12742
13012
  services: array(TopologyServiceSchema).readonly(),
12743
13013
  groupId: string().optional()
12744
13014
  });
13015
+ const TopologyCategoryAddonSchema = object({
13016
+ id: string(),
13017
+ status: string(),
13018
+ cpuPercent: number(),
13019
+ memoryRss: number()
13020
+ });
13021
+ const TopologyCategorySchema = object({
13022
+ category: string(),
13023
+ total: number(),
13024
+ healthy: number(),
13025
+ addons: array(TopologyCategoryAddonSchema).readonly()
13026
+ });
12745
13027
  const TopologyNodeSchema = object({
12746
13028
  id: string(),
12747
13029
  name: string(),
@@ -12766,7 +13048,15 @@ const TopologyNodeSchema = object({
12766
13048
  status: string()
12767
13049
  })
12768
13050
  ).readonly(),
12769
- processes: array(TopologyProcessSchema).readonly()
13051
+ processes: array(TopologyProcessSchema).readonly(),
13052
+ categories: array(TopologyCategorySchema).readonly()
13053
+ });
13054
+ const CapUsageEdgeSchema = object({
13055
+ callerAddonId: string(),
13056
+ providerAddonId: string(),
13057
+ capName: string(),
13058
+ callsPerMin: number(),
13059
+ lastCallAtMs: number()
12770
13060
  });
12771
13061
  const ClusterAddonNodeDeploymentSchema = object({
12772
13062
  nodeId: string(),
@@ -12850,13 +13140,7 @@ const RenameNodeResultSchema = object({
12850
13140
  object({
12851
13141
  windowSeconds: number().int().positive().max(300).default(60)
12852
13142
  }),
12853
- array(object({
12854
- callerAddonId: string(),
12855
- providerAddonId: string(),
12856
- capName: string(),
12857
- callsPerMin: number(),
12858
- lastCallAtMs: number()
12859
- })).readonly(),
13143
+ array(CapUsageEdgeSchema).readonly(),
12860
13144
  { auth: "admin" }
12861
13145
  ),
12862
13146
  /**
@@ -13068,7 +13352,8 @@ const PackageUpdateSchema = object({
13068
13352
  currentVersion: string(),
13069
13353
  latestVersion: string(),
13070
13354
  category: _enum(["addon", "core"]),
13071
- requiresRestart: boolean()
13355
+ requiresRestart: boolean(),
13356
+ isSystem: boolean()
13072
13357
  });
13073
13358
  const PackageVersionInfoSchema = object({
13074
13359
  version: string(),
@@ -13101,6 +13386,42 @@ const UpdateFrameworkPackageResultSchema = object({
13101
13386
  /** Ms-epoch the server scheduled its self-restart. */
13102
13387
  restartingAt: number()
13103
13388
  });
13389
+ const BulkUpdateItemStatusSchema = _enum([
13390
+ "queued",
13391
+ "updating",
13392
+ "done",
13393
+ "done-pending-restart",
13394
+ "failed"
13395
+ ]);
13396
+ const BulkUpdateItemSchema = object({
13397
+ name: string(),
13398
+ isSystem: boolean(),
13399
+ fromVersion: string(),
13400
+ toVersion: string(),
13401
+ status: BulkUpdateItemStatusSchema,
13402
+ error: string().optional(),
13403
+ startedAtMs: number().optional(),
13404
+ completedAtMs: number().optional()
13405
+ });
13406
+ const BulkUpdatePhaseSchema = _enum([
13407
+ "regular",
13408
+ "system",
13409
+ "restarting",
13410
+ "finalizing"
13411
+ ]);
13412
+ const BulkUpdateStateSchema = object({
13413
+ id: string(),
13414
+ nodeId: string(),
13415
+ startedAtMs: number(),
13416
+ completedAtMs: number().optional(),
13417
+ total: number(),
13418
+ completed: number(),
13419
+ failed: number(),
13420
+ current: string().nullable(),
13421
+ phase: BulkUpdatePhaseSchema,
13422
+ cancelled: boolean(),
13423
+ items: array(BulkUpdateItemSchema).readonly()
13424
+ });
13104
13425
  const FrameworkPackageStatusSchema = object({
13105
13426
  packageName: string(),
13106
13427
  currentVersion: string(),
@@ -13238,7 +13559,7 @@ const CustomActionInputSchema = object({
13238
13559
  getLastRestart: method(
13239
13560
  _void(),
13240
13561
  object({
13241
- kind: _enum(["framework-update", "manual", "system"]),
13562
+ kind: _enum(["framework-update", "manual", "system", "framework-bulk-update"]),
13242
13563
  packageName: string().optional(),
13243
13564
  fromVersion: string().optional(),
13244
13565
  toVersion: string().optional(),
@@ -13328,11 +13649,70 @@ const CustomActionInputSchema = object({
13328
13649
  updateFrameworkPackage: method(
13329
13650
  object({
13330
13651
  packageName: string().min(1),
13331
- version: string().optional()
13652
+ version: string().optional(),
13653
+ deferRestart: boolean().optional()
13332
13654
  }),
13333
13655
  UpdateFrameworkPackageResultSchema,
13334
13656
  { kind: "mutation", auth: "admin" }
13335
13657
  ),
13658
+ /**
13659
+ * Kicks off a server-side bulk update operation and returns the bulk
13660
+ * id immediately. The operation runs asynchronously; observe progress
13661
+ * via the `AddonsBulkUpdateProgress` event or `getBulkUpdateState`.
13662
+ * Items with `isSystem: true` use `deferRestart` — the hub restarts
13663
+ * ONCE at the end of the system phase, after all system packages are
13664
+ * installed.
13665
+ *
13666
+ * `items[].version` is REQUIRED — callers must pass the resolved
13667
+ * version from `listUpdates`. There is no `'latest'` default here
13668
+ * (unlike `updatePackage`) to guarantee deterministic bulk rolls.
13669
+ */
13670
+ startBulkUpdate: method(
13671
+ object({
13672
+ nodeId: string(),
13673
+ items: array(object({
13674
+ name: string(),
13675
+ version: string(),
13676
+ isSystem: boolean()
13677
+ })).readonly()
13678
+ }),
13679
+ object({ id: string() }),
13680
+ { kind: "mutation", auth: "admin" }
13681
+ ),
13682
+ /**
13683
+ * Returns the current state of a bulk update by id.
13684
+ * Returns `null` if the id is unknown or has been auto-cleaned
13685
+ * (5 minutes after `completedAt` the record is evicted from memory).
13686
+ */
13687
+ getBulkUpdateState: method(
13688
+ object({ id: string() }),
13689
+ BulkUpdateStateSchema.nullable(),
13690
+ { auth: "admin" }
13691
+ ),
13692
+ /**
13693
+ * Cancels an in-flight bulk update. The update loop exits after the
13694
+ * currently-processing item completes — cancellation is not
13695
+ * instantaneous. Has no effect once the `restarting` phase has been
13696
+ * entered (the hub is already shutting down at that point).
13697
+ * Returns `{ cancelled: false }` if the id is unknown, the operation
13698
+ * has already completed, or the `restarting` phase is active.
13699
+ */
13700
+ cancelBulkUpdate: method(
13701
+ object({ id: string() }),
13702
+ object({ cancelled: boolean() }),
13703
+ { kind: "mutation", auth: "admin" }
13704
+ ),
13705
+ /**
13706
+ * Lists all currently active (non-completed) bulk updates.
13707
+ * If `nodeId` is provided, filters to only bulk updates targeting
13708
+ * that node. Useful for restoring an in-progress banner on a fresh
13709
+ * page load when the UI reconnects mid-operation.
13710
+ */
13711
+ listActiveBulkUpdates: method(
13712
+ object({ nodeId: string().optional() }),
13713
+ array(BulkUpdateStateSchema).readonly(),
13714
+ { auth: "admin" }
13715
+ ),
13336
13716
  getVersions: method(
13337
13717
  object({ name: string() }),
13338
13718
  array(PackageVersionInfoSchema).readonly()
@@ -13460,6 +13840,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13460
13840
  EventCategory2["StreamBrokerOnCamStreamDemand"] = "stream-broker.onCamStreamDemand";
13461
13841
  EventCategory2["StreamBrokerOnCamStreamIdle"] = "stream-broker.onCamStreamIdle";
13462
13842
  EventCategory2["StreamBrokerOnRequestStreamSourceRefresh"] = "stream-broker.onRequestStreamSourceRefresh";
13843
+ EventCategory2["StreamParamsChanged"] = "stream-params.changed";
13463
13844
  EventCategory2["DeviceStateChanged"] = "device.state-changed";
13464
13845
  EventCategory2["BatteryOnStatusChanged"] = "battery.onStatusChanged";
13465
13846
  EventCategory2["DoorbellOnPressed"] = "doorbell.onPressed";
@@ -13507,6 +13888,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13507
13888
  EventCategory2["NetworkTunnelStarted"] = "network.tunnel.started";
13508
13889
  EventCategory2["NetworkTunnelStopped"] = "network.tunnel.stopped";
13509
13890
  EventCategory2["LocalNetworkChanged"] = "network.local.changed";
13891
+ EventCategory2["MeshNetworkChanged"] = "network.mesh.changed";
13510
13892
  EventCategory2["BackupCompleted"] = "backup.completed";
13511
13893
  EventCategory2["BackupRestored"] = "backup.restored";
13512
13894
  EventCategory2["NotificationDispatched"] = "notification.dispatched";
@@ -13517,6 +13899,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13517
13899
  EventCategory2["DeviceAwake"] = "device.awake";
13518
13900
  EventCategory2["DeviceSleeping"] = "device.sleeping";
13519
13901
  EventCategory2["RetentionCleanup"] = "retention.cleanup";
13902
+ EventCategory2["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
13520
13903
  return EventCategory2;
13521
13904
  })(EventCategory || {});
13522
13905
  function createEvent(category, source, data) {
@@ -13666,7 +14049,7 @@ class BaseAddon {
13666
14049
  }
13667
14050
  // ── Settings schemas (override to provide UI) ─────────────────────────
13668
14051
  /** Override to provide global-level settings UI schema. */
13669
- globalSettingsSchema() {
14052
+ globalSettingsSchema(_cap) {
13670
14053
  return null;
13671
14054
  }
13672
14055
  /** Override to provide device-level settings UI schema. */
@@ -13680,8 +14063,8 @@ class BaseAddon {
13680
14063
  // blob and every addon used exactly one of them; the distinction was
13681
14064
  // never semantically load-bearing. `global` won because it was the
13682
14065
  // widely-used one and the name reads naturally (per-node addon config).
13683
- async getGlobalSettings(overlay) {
13684
- const schema = this.globalSettingsSchema();
14066
+ async getGlobalSettings(overlay, cap) {
14067
+ const schema = this.globalSettingsSchema(cap);
13685
14068
  if (!schema) return { sections: [] };
13686
14069
  const raw = await this._ctx?.settings?.readAddonStore() ?? {};
13687
14070
  return hydrateSchema(schema, overlay ? { ...raw, ...overlay } : raw);
@@ -13958,4 +14341,4 @@ export {
13958
14341
  tuple as t,
13959
14342
  zoneAnalyticsCapability as z
13960
14343
  };
13961
- //# sourceMappingURL=index-CGAj-pkn.mjs.map
14344
+ //# sourceMappingURL=index-BrTlzsrE.mjs.map