@camstack/addon-post-analysis 0.1.18 → 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-DafwGlkQ.js → index-BFbwYH1P.js} +414 -45
  6. package/dist/index-BFbwYH1P.js.map +1 -0
  7. package/dist/{index-CIJfmsWX.mjs → index-BrTlzsrE.mjs} +414 -45
  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-B3kCe2qM.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-CuWzic_f.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-CUXiTSWS.mjs → index-Dy2V7VOm.mjs} +3775 -3279
  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-BKsM_JGg.js → recording-coordinator-BoGr5moz.js} +2 -2
  34. package/dist/{recording-coordinator-BKsM_JGg.js.map → recording-coordinator-BoGr5moz.js.map} +1 -1
  35. package/dist/{recording-coordinator-Bw3N1gYu.mjs → recording-coordinator-CsYH9LqF.mjs} +2 -2
  36. package/dist/{recording-coordinator-Bw3N1gYu.mjs.map → recording-coordinator-CsYH9LqF.mjs.map} +1 -1
  37. package/package.json +1 -1
  38. package/dist/index-CIJfmsWX.mjs.map +0 -1
  39. package/dist/index-DafwGlkQ.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
@@ -22,7 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
25
- const index = require("../index-DafwGlkQ.js");
25
+ const index = require("../index-BFbwYH1P.js");
26
26
  const core = require("@camstack/core");
27
27
  const path = require("node:path");
28
28
  const fs = require("node:fs");
@@ -1,4 +1,4 @@
1
- import { R as RUNTIME_TO_FORMAT$1, P as PYTHON_SCRIPT, f as BACKEND_TO_FORMAT$1, B as BaseAddon, g as embeddingEncoderCapability } from "../index-CIJfmsWX.mjs";
1
+ import { R as RUNTIME_TO_FORMAT$1, P as PYTHON_SCRIPT, f as BACKEND_TO_FORMAT$1, B as BaseAddon, g as embeddingEncoderCapability } from "../index-BrTlzsrE.mjs";
2
2
  import { ModelDownloadService } from "@camstack/core";
3
3
  import * as path from "node:path";
4
4
  import * as fs from "node:fs";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const index = require("../index-DafwGlkQ.js");
3
+ const index = require("../index-BFbwYH1P.js");
4
4
  const shmRing = require("@camstack/shm-ring");
5
5
  const sharp = require("sharp");
6
6
  const DEFAULT_ENRICHMENT_CONFIG = {
@@ -1,4 +1,4 @@
1
- import { E as EventCategory, c as createEvent, o as object, t as tuple, n as number, s as string, b as boolean, a as array, _ as _enum, B as BaseAddon, d as asJsonObject } from "../index-CIJfmsWX.mjs";
1
+ import { E as EventCategory, c as createEvent, o as object, t as tuple, n as number, s as string, b as boolean, a as array, _ as _enum, B as BaseAddon, d as asJsonObject } from "../index-BrTlzsrE.mjs";
2
2
  import { FrameRingReaderCache } from "@camstack/shm-ring";
3
3
  import sharp from "sharp";
4
4
  const DEFAULT_ENRICHMENT_CONFIG = {
@@ -4779,6 +4779,16 @@ function record(keyType, valueType, params) {
4779
4779
  ...normalizeParams(params)
4780
4780
  });
4781
4781
  }
4782
+ function partialRecord(keyType, valueType, params) {
4783
+ const k = clone(keyType);
4784
+ k._zod.values = void 0;
4785
+ return new ZodRecord({
4786
+ type: "record",
4787
+ keyType: k,
4788
+ valueType,
4789
+ ...normalizeParams(params)
4790
+ });
4791
+ }
4782
4792
  const ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
4783
4793
  $ZodEnum.init(inst, def);
4784
4794
  ZodType.init(inst, def);
@@ -5055,6 +5065,37 @@ function _instanceof(cls, params = {}) {
5055
5065
  };
5056
5066
  return inst;
5057
5067
  }
5068
+ const wiringProbeKindSchema = _enum(["singleton", "device", "widget"]);
5069
+ const wiringProbeResultSchema = object({
5070
+ capName: string(),
5071
+ kind: wiringProbeKindSchema,
5072
+ deviceId: number().optional(),
5073
+ reachable: boolean(),
5074
+ latencyMs: number(),
5075
+ error: string().optional()
5076
+ });
5077
+ const wiringAddonHealthSchema = object({
5078
+ addonId: string(),
5079
+ caps: array(wiringProbeResultSchema).readonly(),
5080
+ widgets: array(wiringProbeResultSchema).readonly()
5081
+ });
5082
+ const wiringNodeHealthSchema = object({
5083
+ nodeId: string(),
5084
+ addons: array(wiringAddonHealthSchema).readonly()
5085
+ });
5086
+ object({
5087
+ /** True only when every probed target is reachable. */
5088
+ ok: boolean(),
5089
+ /** True when at least one target is unreachable. */
5090
+ degraded: boolean(),
5091
+ checkedAt: string(),
5092
+ nodes: array(wiringNodeHealthSchema).readonly(),
5093
+ summary: object({
5094
+ total: number(),
5095
+ reachable: number(),
5096
+ unreachable: number()
5097
+ })
5098
+ });
5058
5099
  const MODEL_FORMATS = ["onnx", "coreml", "openvino", "tflite", "pt"];
5059
5100
  const WELL_KNOWN_TABS = [
5060
5101
  { id: "overview", label: "Overview", icon: "layout-dashboard", order: -10 },
@@ -6584,7 +6625,7 @@ const SpatialDetectionSchema = object({
6584
6625
  bbox: BoundingBoxSchema
6585
6626
  });
6586
6627
  const AudioChunkInputSchema = object({
6587
- data: _instanceof(Float32Array),
6628
+ data: _instanceof(Uint8Array),
6588
6629
  sampleRate: number(),
6589
6630
  channels: number(),
6590
6631
  timestamp: number(),
@@ -7255,7 +7296,23 @@ const RunnerCameraConfigSchema = object({
7255
7296
  * whenever its `zones` device-state slice changes, so the runner's
7256
7297
  * copy stays in sync. Empty array → no zone filtering.
7257
7298
  */
7258
- zones: array(ZoneSchema).readonly().default([])
7299
+ zones: array(ZoneSchema).readonly().default([]),
7300
+ /**
7301
+ * When true (default) and the camera's `motionSources` contains only
7302
+ * `'onboard'`, the runner dynamically opens the same WASM frame-diff
7303
+ * motion-frames subscription on each `MotionOnMotionChanged
7304
+ * source:'onboard'` event and tears it down after `motionCooldownMs`.
7305
+ * This causes `runMotionAnalysis` to emit `MotionZonesRaw` /
7306
+ * `MotionAnalysis` during active-motion windows without the
7307
+ * substream being held open continuously.
7308
+ *
7309
+ * Set to `false` to disable the dynamic analyzer for this camera
7310
+ * (e.g. very low-bandwidth links where the extra substream is
7311
+ * undesirable). Has no effect when `motionSources` already includes
7312
+ * `'analyzer'` — the analyzer runs continuously in that case and
7313
+ * this gate is bypassed.
7314
+ */
7315
+ onboardMotionDrivesAnalyzer: boolean().default(true)
7259
7316
  });
7260
7317
  const RunnerLocalLoadSchema = object({
7261
7318
  /** Moleculer node id of this runner instance. */
@@ -7392,22 +7449,68 @@ MotionTriggerStatusSchema.extend({
7392
7449
  }) }
7393
7450
  }
7394
7451
  });
7452
+ const MaskPointSchema = object({
7453
+ x: number(),
7454
+ y: number()
7455
+ });
7456
+ const MaskRectShapeSchema = object({
7457
+ kind: literal("rect"),
7458
+ x: number(),
7459
+ y: number(),
7460
+ width: number(),
7461
+ height: number()
7462
+ });
7463
+ const MaskPolygonShapeSchema = object({
7464
+ kind: literal("polygon"),
7465
+ points: array(MaskPointSchema)
7466
+ });
7467
+ const MaskGridShapeSchema = object({
7468
+ kind: literal("grid"),
7469
+ gridWidth: number(),
7470
+ gridHeight: number(),
7471
+ cells: array(boolean())
7472
+ });
7473
+ const MaskLineShapeSchema = object({
7474
+ kind: literal("line"),
7475
+ points: array(MaskPointSchema)
7476
+ });
7477
+ discriminatedUnion("kind", [
7478
+ MaskRectShapeSchema,
7479
+ MaskPolygonShapeSchema,
7480
+ MaskGridShapeSchema,
7481
+ MaskLineShapeSchema
7482
+ ]);
7483
+ const MaskShapeKindSchema = _enum(["rect", "polygon", "grid", "line"]);
7484
+ const MaskPolygonVerticesSchema = object({
7485
+ min: number(),
7486
+ max: number()
7487
+ });
7488
+ const MaskGridDimsSchema = object({
7489
+ width: number(),
7490
+ height: number()
7491
+ });
7492
+ const MotionZoneRegionSchema = object({
7493
+ id: number(),
7494
+ enabled: boolean(),
7495
+ shape: MaskGridShapeSchema
7496
+ });
7395
7497
  object({
7396
7498
  enabled: boolean(),
7397
7499
  sensitivity: number(),
7398
- /** Row-major active-cell grid. Length = gridWidth*gridHeight (see getOptions). */
7399
- cells: array(boolean()),
7500
+ /** Grid region(s). Today exactly one `grid` shape. */
7501
+ regions: array(MotionZoneRegionSchema),
7400
7502
  lastFetchedAt: number()
7401
7503
  });
7402
7504
  const MotionZoneOptionsSchema = object({
7403
- gridWidth: number(),
7404
- gridHeight: number(),
7505
+ maxRegions: number(),
7506
+ supportedShapes: array(MaskShapeKindSchema),
7507
+ grid: MaskGridDimsSchema,
7405
7508
  sensitivity: object({ min: number(), max: number(), step: number() })
7406
7509
  });
7407
7510
  const MotionZonePatchSchema = object({
7408
7511
  enabled: boolean().optional(),
7409
7512
  sensitivity: number().optional(),
7410
- cells: array(boolean()).optional()
7513
+ regions: array(MotionZoneRegionSchema).optional()
7411
7514
  });
7412
7515
  ({
7413
7516
  deviceTypes: [DeviceType.Camera],
@@ -7420,6 +7523,102 @@ const MotionZonePatchSchema = object({
7420
7523
  )
7421
7524
  }
7422
7525
  });
7526
+ const NativeObjectClassEnum = _enum([
7527
+ "person",
7528
+ "vehicle",
7529
+ "animal",
7530
+ "face",
7531
+ "package",
7532
+ "other"
7533
+ ]);
7534
+ const NativeDetectionSchema = object({
7535
+ class: NativeObjectClassEnum,
7536
+ timestamp: number(),
7537
+ /** Firmware-provided confidence [0..1]. Reolink pushes don't carry it → undefined. */
7538
+ confidence: number().min(0).max(1).optional()
7539
+ });
7540
+ const NativeObjectDetectionStatusSchema = object({
7541
+ /**
7542
+ * Last observed instance per class. Missing entries mean the class
7543
+ * is supported but nothing has been seen since the provider started.
7544
+ *
7545
+ * MUST be a partial record: providers seed an empty `{}` on cold-start
7546
+ * and write one class at a time as detections arrive. In Zod 4
7547
+ * `z.record(enum, …)` is EXHAUSTIVE (requires every enum key), so a
7548
+ * partial write throws "expected object, received undefined" for every
7549
+ * unseen class. `z.partialRecord` keeps the enum-key narrowing while
7550
+ * allowing the sparse shape the providers actually write.
7551
+ */
7552
+ lastByClass: partialRecord(NativeObjectClassEnum, NativeDetectionSchema.nullable()),
7553
+ /** Classes the firmware is capable of detecting — enumerated at device register. */
7554
+ supportedClasses: array(NativeObjectClassEnum).readonly(),
7555
+ /**
7556
+ * Whether forwarding of onboard AI detections is enabled for this device.
7557
+ * Default true (on cold-start) — detections flow unconditionally before
7558
+ * the toggle is saved, so defaulting true preserves existing behaviour.
7559
+ */
7560
+ enabled: boolean()
7561
+ });
7562
+ NativeObjectDetectionStatusSchema.extend({
7563
+ /** Required by createRuntimeStateBridge — epoch ms of last refresh. */
7564
+ lastFetchedAt: number()
7565
+ });
7566
+ ({
7567
+ deviceTypes: [DeviceType.Camera],
7568
+ methods: {
7569
+ setEnabled: method(
7570
+ object({ deviceId: number(), enabled: boolean() }),
7571
+ _void(),
7572
+ { kind: "mutation", auth: "admin" }
7573
+ )
7574
+ },
7575
+ events: {
7576
+ onDetected: { data: object({
7577
+ deviceId: number(),
7578
+ detection: NativeDetectionSchema
7579
+ }) }
7580
+ }
7581
+ });
7582
+ const PrivacyMaskShapeSchema = discriminatedUnion("kind", [
7583
+ MaskRectShapeSchema,
7584
+ MaskPolygonShapeSchema
7585
+ ]);
7586
+ const PrivacyMaskRegionSchema = object({
7587
+ /** Slot id, 0-based. Stable across read/write. */
7588
+ id: number(),
7589
+ /** Whether this zone is active (blanked out by the camera). */
7590
+ enabled: boolean(),
7591
+ shape: PrivacyMaskShapeSchema
7592
+ });
7593
+ object({
7594
+ enabled: boolean(),
7595
+ /** Active zones (normalized 0..1). Length ≤ maxRegions. */
7596
+ regions: array(PrivacyMaskRegionSchema),
7597
+ lastFetchedAt: number()
7598
+ });
7599
+ const PrivacyMaskOptionsSchema = object({
7600
+ /** Maximum number of supported zones. */
7601
+ maxRegions: number(),
7602
+ /** Shape kinds this camera accepts — Reolink: ['rect']; Hikvision: ['rect','polygon']. */
7603
+ supportedShapes: array(MaskShapeKindSchema),
7604
+ /** Polygon vertex bounds when 'polygon' is supported (Hikvision: {min:4,max:4}). */
7605
+ polygonVertices: MaskPolygonVerticesSchema.optional()
7606
+ });
7607
+ const PrivacyMaskPatchSchema = object({
7608
+ enabled: boolean().optional(),
7609
+ regions: array(PrivacyMaskRegionSchema).optional()
7610
+ });
7611
+ ({
7612
+ deviceTypes: [DeviceType.Camera],
7613
+ methods: {
7614
+ getOptions: method(object({ deviceId: number() }), PrivacyMaskOptionsSchema),
7615
+ setMask: method(
7616
+ object({ deviceId: number(), patch: PrivacyMaskPatchSchema }),
7617
+ _void(),
7618
+ { kind: "mutation", auth: "admin" }
7619
+ )
7620
+ }
7621
+ });
7423
7622
  const AutotrackTargetTypeSchema = string().describe("Vendor target string (people/vehicle/pet); empty = camera default");
7424
7623
  const PtzAutotrackSettingsSchema = object({
7425
7624
  targetType: AutotrackTargetTypeSchema,
@@ -7949,7 +8148,8 @@ const SettingsUpdateResultSchema = object({
7949
8148
  object({
7950
8149
  addonId: string(),
7951
8150
  nodeId: string().optional(),
7952
- overlay: record(string(), unknown()).optional()
8151
+ overlay: record(string(), unknown()).optional(),
8152
+ cap: string().optional()
7953
8153
  }),
7954
8154
  SettingsSchemaWithValuesSchema.nullable()
7955
8155
  ),
@@ -8680,7 +8880,14 @@ const OauthIntegrationDescriptorSchema = object({
8680
8880
  /** Allowed redirect_uri prefixes. /api/oauth2/authorize rejects any
8681
8881
  * redirect_uri that does not start with one of these. Required —
8682
8882
  * an empty list means the integration can never complete linking. */
8683
- allowedRedirectPrefixes: array(string()).min(1)
8883
+ allowedRedirectPrefixes: array(string()).min(1),
8884
+ /** Optional public origin (no trailing slash) that this integration's
8885
+ * issued codes/tokens should carry as the `hubUrl` claim — typically the
8886
+ * operator-selected external-access endpoint resolved by the addon. When
8887
+ * present, /api/oauth2/authorize bakes THIS into the code instead of the
8888
+ * hub-global `publicHubUrl()`, so a forked exporter addon (which can't set
8889
+ * the hub's env) drives the claim that its cloud Lambda routes back on. */
8890
+ hubUrl: string().optional()
8684
8891
  });
8685
8892
  ({
8686
8893
  methods: {
@@ -9298,7 +9505,20 @@ const WebrtcStreamChoiceSchema = object({
9298
9505
  object({
9299
9506
  deviceId: number().int().nonnegative(),
9300
9507
  target: WebrtcStreamTargetSchema,
9301
- hints: webrtcClientHintsSchema.optional()
9508
+ hints: webrtcClientHintsSchema.optional(),
9509
+ /**
9510
+ * SERVER-INJECTED — NOT a client hint. The hub layer that holds
9511
+ * the tRPC request context (and therefore the client IP) sets
9512
+ * this to `true` when the viewer's source IP is non-LAN
9513
+ * (4G/CGNAT/internet). The broker then forces TURN-relay-only
9514
+ * ICE for the session so a CGNAT client (which can only offer a
9515
+ * relay candidate) gets a clean relay↔relay media path instead
9516
+ * of werift nominating a dead host/hairpin-srflx pair. LAN
9517
+ * clients leave this absent/false and keep the low-latency
9518
+ * direct (host/srflx) path. Clients MUST NOT send this — the
9519
+ * server overwrites it from the request context.
9520
+ */
9521
+ relayOnly: boolean().optional()
9302
9522
  }),
9303
9523
  object({ sessionId: string(), sdpOffer: string() }),
9304
9524
  { kind: "mutation" }
@@ -9321,7 +9541,22 @@ const WebrtcStreamChoiceSchema = object({
9321
9541
  deviceId: number().int().nonnegative(),
9322
9542
  target: WebrtcStreamTargetSchema.optional(),
9323
9543
  sdpOffer: string(),
9324
- sessionId: string().optional()
9544
+ sessionId: string().optional(),
9545
+ /**
9546
+ * Force TURN-relay-only ICE for this session. Two kinds of caller
9547
+ * set it:
9548
+ * - A cloud peer like Alexa's RTCSessionController (reachable
9549
+ * only via TURN, never our host/srflx behind NAT) passes
9550
+ * `true` from its own trusted addon context.
9551
+ * - The hub injects it for browser client-offer viewers from the
9552
+ * request's source IP (non-LAN ⇒ true), exactly as it does for
9553
+ * `createSession`.
9554
+ * A LAN/Tailscale browser doing client-offer passthrough leaves it
9555
+ * absent/false so a direct host pair carries full native quality.
9556
+ * Untrusted browser clients MUST NOT send it — the hub overwrites
9557
+ * it from the request context.
9558
+ */
9559
+ relayOnly: boolean().optional()
9325
9560
  }),
9326
9561
  object({ sessionId: string(), sdpAnswer: string() }),
9327
9562
  { kind: "mutation" }
@@ -9335,6 +9570,46 @@ const WebrtcStreamChoiceSchema = object({
9335
9570
  _void(),
9336
9571
  { kind: "mutation" }
9337
9572
  ),
9573
+ /**
9574
+ * Trickle ICE — add a remote (client) ICE candidate to a live session.
9575
+ * Lets the client send its SDP offer/answer IMMEDIATELY (before ICE
9576
+ * gathering finishes) and deliver candidates as they arrive, so the
9577
+ * connection establishes in ~0s instead of waiting for full gathering.
9578
+ * The dual of `getIceCandidates`. Mirrors Scrypted's signaling.
9579
+ */
9580
+ addIceCandidate: method(
9581
+ object({
9582
+ deviceId: number().int().nonnegative(),
9583
+ sessionId: string(),
9584
+ candidate: string(),
9585
+ sdpMid: string().nullable().optional(),
9586
+ sdpMLineIndex: number().int().nullable().optional()
9587
+ }),
9588
+ _void(),
9589
+ { kind: "mutation" }
9590
+ ),
9591
+ /**
9592
+ * Trickle ICE — poll the server's gathered ICE candidates for a session.
9593
+ * The server answers immediately (no gathering wait) and the client polls
9594
+ * this to receive host/srflx/relay candidates as werift gathers them,
9595
+ * adding each to its PeerConnection. Returns all candidates gathered so
9596
+ * far; the client dedupes. `done` flips true once gathering completes.
9597
+ */
9598
+ getIceCandidates: method(
9599
+ object({
9600
+ deviceId: number().int().nonnegative(),
9601
+ sessionId: string()
9602
+ }),
9603
+ object({
9604
+ candidates: array(object({
9605
+ candidate: string(),
9606
+ sdpMid: string().nullable(),
9607
+ sdpMLineIndex: number().int().nullable()
9608
+ })),
9609
+ done: boolean()
9610
+ }),
9611
+ { kind: "query" }
9612
+ ),
9338
9613
  closeSession: method(
9339
9614
  object({
9340
9615
  deviceId: number().int().nonnegative(),
@@ -11013,6 +11288,9 @@ const recordingEngineCapability = {
11013
11288
  ({
11014
11289
  deviceTypes: [DeviceType.Camera]
11015
11290
  });
11291
+ ({
11292
+ deviceTypes: [DeviceType.Camera]
11293
+ });
11016
11294
  const TrackStateSchema = _enum(["new", "entered", "left", "moving", "idle"]);
11017
11295
  const EventKindSchema = _enum(["motion", "object", "audio"]);
11018
11296
  const TrackPositionSchema = object({
@@ -11846,36 +12124,28 @@ const IntercomStatusSchema = object({
11846
12124
  }) }
11847
12125
  }
11848
12126
  });
11849
- const NativeObjectClassEnum = _enum([
11850
- "person",
11851
- "vehicle",
11852
- "animal",
11853
- "face",
11854
- "package",
11855
- "other"
11856
- ]);
11857
- const NativeDetectionSchema = object({
11858
- class: NativeObjectClassEnum,
11859
- timestamp: number(),
11860
- /** Firmware-provided confidence [0..1]. Reolink pushes don't carry it → undefined. */
11861
- confidence: number().min(0).max(1).optional()
11862
- });
11863
- object({
11864
- /**
11865
- * Last observed instance per class. Undefined entries mean the class
11866
- * is supported but nothing has been seen since the provider started.
11867
- */
11868
- lastByClass: record(NativeObjectClassEnum, NativeDetectionSchema.nullable()),
11869
- /** Classes the firmware is capable of detecting — enumerated at device register. */
11870
- supportedClasses: array(NativeObjectClassEnum).readonly()
12127
+ const CamStreamDescriptorSchema = object({
12128
+ camStreamId: string().min(1),
12129
+ kind: CamStreamKindSchema,
12130
+ url: string().optional(),
12131
+ codec: string().optional(),
12132
+ resolution: CamStreamResolutionSchema.optional(),
12133
+ fps: number().positive().optional(),
12134
+ label: string().optional(),
12135
+ /** Device-level features (e.g. `battery-operated`) — drives broker policy. */
12136
+ deviceFeatures: array(string()).optional(),
12137
+ /** Eligible for automatic profile assignment. Absent = `true`. */
12138
+ autoEligible: boolean().optional(),
12139
+ /** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
12140
+ metadata: record(string(), unknown()).optional()
11871
12141
  });
11872
12142
  ({
11873
12143
  deviceTypes: [DeviceType.Camera],
11874
- events: {
11875
- onDetected: { data: object({
11876
- deviceId: number(),
11877
- detection: NativeDetectionSchema
11878
- }) }
12144
+ methods: {
12145
+ getCatalog: method(
12146
+ object({ deviceId: number().int().nonnegative() }),
12147
+ array(CamStreamDescriptorSchema).readonly()
12148
+ )
11879
12149
  }
11880
12150
  });
11881
12151
  const ModelFormatSchema = _enum(MODEL_FORMATS);
@@ -13083,7 +13353,8 @@ const PackageUpdateSchema = object({
13083
13353
  currentVersion: string(),
13084
13354
  latestVersion: string(),
13085
13355
  category: _enum(["addon", "core"]),
13086
- requiresRestart: boolean()
13356
+ requiresRestart: boolean(),
13357
+ isSystem: boolean()
13087
13358
  });
13088
13359
  const PackageVersionInfoSchema = object({
13089
13360
  version: string(),
@@ -13116,6 +13387,42 @@ const UpdateFrameworkPackageResultSchema = object({
13116
13387
  /** Ms-epoch the server scheduled its self-restart. */
13117
13388
  restartingAt: number()
13118
13389
  });
13390
+ const BulkUpdateItemStatusSchema = _enum([
13391
+ "queued",
13392
+ "updating",
13393
+ "done",
13394
+ "done-pending-restart",
13395
+ "failed"
13396
+ ]);
13397
+ const BulkUpdateItemSchema = object({
13398
+ name: string(),
13399
+ isSystem: boolean(),
13400
+ fromVersion: string(),
13401
+ toVersion: string(),
13402
+ status: BulkUpdateItemStatusSchema,
13403
+ error: string().optional(),
13404
+ startedAtMs: number().optional(),
13405
+ completedAtMs: number().optional()
13406
+ });
13407
+ const BulkUpdatePhaseSchema = _enum([
13408
+ "regular",
13409
+ "system",
13410
+ "restarting",
13411
+ "finalizing"
13412
+ ]);
13413
+ const BulkUpdateStateSchema = object({
13414
+ id: string(),
13415
+ nodeId: string(),
13416
+ startedAtMs: number(),
13417
+ completedAtMs: number().optional(),
13418
+ total: number(),
13419
+ completed: number(),
13420
+ failed: number(),
13421
+ current: string().nullable(),
13422
+ phase: BulkUpdatePhaseSchema,
13423
+ cancelled: boolean(),
13424
+ items: array(BulkUpdateItemSchema).readonly()
13425
+ });
13119
13426
  const FrameworkPackageStatusSchema = object({
13120
13427
  packageName: string(),
13121
13428
  currentVersion: string(),
@@ -13253,7 +13560,7 @@ const CustomActionInputSchema = object({
13253
13560
  getLastRestart: method(
13254
13561
  _void(),
13255
13562
  object({
13256
- kind: _enum(["framework-update", "manual", "system"]),
13563
+ kind: _enum(["framework-update", "manual", "system", "framework-bulk-update"]),
13257
13564
  packageName: string().optional(),
13258
13565
  fromVersion: string().optional(),
13259
13566
  toVersion: string().optional(),
@@ -13343,11 +13650,70 @@ const CustomActionInputSchema = object({
13343
13650
  updateFrameworkPackage: method(
13344
13651
  object({
13345
13652
  packageName: string().min(1),
13346
- version: string().optional()
13653
+ version: string().optional(),
13654
+ deferRestart: boolean().optional()
13347
13655
  }),
13348
13656
  UpdateFrameworkPackageResultSchema,
13349
13657
  { kind: "mutation", auth: "admin" }
13350
13658
  ),
13659
+ /**
13660
+ * Kicks off a server-side bulk update operation and returns the bulk
13661
+ * id immediately. The operation runs asynchronously; observe progress
13662
+ * via the `AddonsBulkUpdateProgress` event or `getBulkUpdateState`.
13663
+ * Items with `isSystem: true` use `deferRestart` — the hub restarts
13664
+ * ONCE at the end of the system phase, after all system packages are
13665
+ * installed.
13666
+ *
13667
+ * `items[].version` is REQUIRED — callers must pass the resolved
13668
+ * version from `listUpdates`. There is no `'latest'` default here
13669
+ * (unlike `updatePackage`) to guarantee deterministic bulk rolls.
13670
+ */
13671
+ startBulkUpdate: method(
13672
+ object({
13673
+ nodeId: string(),
13674
+ items: array(object({
13675
+ name: string(),
13676
+ version: string(),
13677
+ isSystem: boolean()
13678
+ })).readonly()
13679
+ }),
13680
+ object({ id: string() }),
13681
+ { kind: "mutation", auth: "admin" }
13682
+ ),
13683
+ /**
13684
+ * Returns the current state of a bulk update by id.
13685
+ * Returns `null` if the id is unknown or has been auto-cleaned
13686
+ * (5 minutes after `completedAt` the record is evicted from memory).
13687
+ */
13688
+ getBulkUpdateState: method(
13689
+ object({ id: string() }),
13690
+ BulkUpdateStateSchema.nullable(),
13691
+ { auth: "admin" }
13692
+ ),
13693
+ /**
13694
+ * Cancels an in-flight bulk update. The update loop exits after the
13695
+ * currently-processing item completes — cancellation is not
13696
+ * instantaneous. Has no effect once the `restarting` phase has been
13697
+ * entered (the hub is already shutting down at that point).
13698
+ * Returns `{ cancelled: false }` if the id is unknown, the operation
13699
+ * has already completed, or the `restarting` phase is active.
13700
+ */
13701
+ cancelBulkUpdate: method(
13702
+ object({ id: string() }),
13703
+ object({ cancelled: boolean() }),
13704
+ { kind: "mutation", auth: "admin" }
13705
+ ),
13706
+ /**
13707
+ * Lists all currently active (non-completed) bulk updates.
13708
+ * If `nodeId` is provided, filters to only bulk updates targeting
13709
+ * that node. Useful for restoring an in-progress banner on a fresh
13710
+ * page load when the UI reconnects mid-operation.
13711
+ */
13712
+ listActiveBulkUpdates: method(
13713
+ object({ nodeId: string().optional() }),
13714
+ array(BulkUpdateStateSchema).readonly(),
13715
+ { auth: "admin" }
13716
+ ),
13351
13717
  getVersions: method(
13352
13718
  object({ name: string() }),
13353
13719
  array(PackageVersionInfoSchema).readonly()
@@ -13475,6 +13841,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13475
13841
  EventCategory2["StreamBrokerOnCamStreamDemand"] = "stream-broker.onCamStreamDemand";
13476
13842
  EventCategory2["StreamBrokerOnCamStreamIdle"] = "stream-broker.onCamStreamIdle";
13477
13843
  EventCategory2["StreamBrokerOnRequestStreamSourceRefresh"] = "stream-broker.onRequestStreamSourceRefresh";
13844
+ EventCategory2["StreamParamsChanged"] = "stream-params.changed";
13478
13845
  EventCategory2["DeviceStateChanged"] = "device.state-changed";
13479
13846
  EventCategory2["BatteryOnStatusChanged"] = "battery.onStatusChanged";
13480
13847
  EventCategory2["DoorbellOnPressed"] = "doorbell.onPressed";
@@ -13522,6 +13889,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13522
13889
  EventCategory2["NetworkTunnelStarted"] = "network.tunnel.started";
13523
13890
  EventCategory2["NetworkTunnelStopped"] = "network.tunnel.stopped";
13524
13891
  EventCategory2["LocalNetworkChanged"] = "network.local.changed";
13892
+ EventCategory2["MeshNetworkChanged"] = "network.mesh.changed";
13525
13893
  EventCategory2["BackupCompleted"] = "backup.completed";
13526
13894
  EventCategory2["BackupRestored"] = "backup.restored";
13527
13895
  EventCategory2["NotificationDispatched"] = "notification.dispatched";
@@ -13532,6 +13900,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13532
13900
  EventCategory2["DeviceAwake"] = "device.awake";
13533
13901
  EventCategory2["DeviceSleeping"] = "device.sleeping";
13534
13902
  EventCategory2["RetentionCleanup"] = "retention.cleanup";
13903
+ EventCategory2["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
13535
13904
  return EventCategory2;
13536
13905
  })(EventCategory || {});
13537
13906
  function createEvent(category, source, data) {
@@ -13681,7 +14050,7 @@ class BaseAddon {
13681
14050
  }
13682
14051
  // ── Settings schemas (override to provide UI) ─────────────────────────
13683
14052
  /** Override to provide global-level settings UI schema. */
13684
- globalSettingsSchema() {
14053
+ globalSettingsSchema(_cap) {
13685
14054
  return null;
13686
14055
  }
13687
14056
  /** Override to provide device-level settings UI schema. */
@@ -13695,8 +14064,8 @@ class BaseAddon {
13695
14064
  // blob and every addon used exactly one of them; the distinction was
13696
14065
  // never semantically load-bearing. `global` won because it was the
13697
14066
  // widely-used one and the name reads naturally (per-node addon config).
13698
- async getGlobalSettings(overlay) {
13699
- const schema = this.globalSettingsSchema();
14067
+ async getGlobalSettings(overlay, cap) {
14068
+ const schema = this.globalSettingsSchema(cap);
13700
14069
  if (!schema) return { sections: [] };
13701
14070
  const raw = await this._ctx?.settings?.readAddonStore() ?? {};
13702
14071
  return hydrateSchema(schema, overlay ? { ...raw, ...overlay } : raw);
@@ -13971,4 +14340,4 @@ exports.recordingEngineCapability = recordingEngineCapability;
13971
14340
  exports.string = string;
13972
14341
  exports.tuple = tuple;
13973
14342
  exports.zoneAnalyticsCapability = zoneAnalyticsCapability;
13974
- //# sourceMappingURL=index-DafwGlkQ.js.map
14343
+ //# sourceMappingURL=index-BFbwYH1P.js.map