@camstack/addon-provider-reolink 1.2.176 → 1.2.178

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 (3) hide show
  1. package/dist/addon.js +1231 -546
  2. package/dist/addon.mjs +1231 -546
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -35,7 +35,7 @@ let node_os = require("node:os");
35
35
  node_os = require_chunk.__toESM(node_os);
36
36
  let node_fs = require("node:fs");
37
37
  node_fs = require_chunk.__toESM(node_fs, 1);
38
- //#region ../types/dist/event-category-BGmz_oxW.mjs
38
+ //#region ../types/dist/event-category-B_0XEcLF.mjs
39
39
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
40
40
  EventCategory["SystemBoot"] = "system.boot";
41
41
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -536,15 +536,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
536
536
  EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
537
537
  EventCategory["AgentBackupActivated"] = "agent.backup.activated";
538
538
  EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
539
- /**
540
- * Per-agent hwaccel preference changed (user override set, cleared, or
541
- * re-probed). Observability event — decoders pull the current pref at
542
- * `createSession`, so running sessions keep their current backend until
543
- * they rotate naturally (camera add/remove, stream restart). Future
544
- * work can wire a listener in stream-broker that force-rotates live
545
- * sessions; for now this event powers logs + admin-UI toast feedback.
546
- */
547
- EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
548
539
  EventCategory["MotionAnalysis"] = "detection.motion-analysis";
549
540
  /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
550
541
  EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
@@ -5415,7 +5406,7 @@ var ZodIssueCode = {
5415
5406
  var ZodFirstPartyTypeKind;
5416
5407
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5417
5408
  //#endregion
5418
- //#region ../types/dist/sleep-DXKLNFvA.mjs
5409
+ //#region ../types/dist/sleep-B0JG7-_F.mjs
5419
5410
  /**
5420
5411
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5421
5412
  * window to float samples (D455).
@@ -6781,32 +6772,12 @@ object({
6781
6772
  audioCodec: string().optional(),
6782
6773
  metadata: record(string(), unknown()).readonly().optional()
6783
6774
  });
6784
- var EncodedPacketSchema = object({
6785
- type: _enum(["video", "audio"]),
6786
- data: _instanceof(Uint8Array),
6787
- pts: number(),
6788
- dts: number(),
6789
- keyframe: boolean(),
6790
- codec: string()
6791
- });
6792
- var DecodedFrameSchema = object({
6793
- data: _instanceof(Uint8Array),
6794
- width: number(),
6795
- height: number(),
6796
- format: _enum([
6797
- "jpeg",
6798
- "rgb",
6799
- "bgr",
6800
- "yuv420",
6801
- "gray"
6802
- ]),
6803
- timestamp: number()
6804
- });
6805
6775
  /**
6806
6776
  * Wire schema for `FrameHandle` — a zero-pixel, serialisable reference to a
6807
6777
  * frame in a shared-memory ring (Phase 5 / D9). Mirrors the `FrameHandle` TS
6808
- * interface in `interfaces/frame-handle.ts` field-for-field so a decoder cap
6809
- * method (`pullHandles`) can carry handles over tRPC / Moleculer.
6778
+ * interface in `interfaces/frame-handle.ts` field-for-field so a cap method
6779
+ * (the runner's native-crop and pipeline-executor inputs) can carry handles
6780
+ * over tRPC / Moleculer.
6810
6781
  *
6811
6782
  * The `satisfies` assertion below pins this schema to the interface: if a
6812
6783
  * field is added to / removed from `FrameHandle` without a matching schema
@@ -6832,50 +6803,6 @@ var FrameHandleSchema = object({
6832
6803
  slotCount: number().int().positive()
6833
6804
  });
6834
6805
  /**
6835
- * Pixel format a frame-handle subscriber can request from the broker
6836
- * (Phase 5 / D9). The packed, raster subset of `FrameFormat` — the formats a
6837
- * `frameSink: 'shm'` decoder session can write into a `FrameRing` slot.
6838
- * `jpeg` is excluded: a variable-length stream is not a fixed-stride ring
6839
- * payload, and no decoded-frame consumer requests it over the shm plane.
6840
- */
6841
- var FrameHandleFormatSchema = _enum([
6842
- "rgb",
6843
- "bgr",
6844
- "yuv420",
6845
- "gray"
6846
- ]);
6847
- /**
6848
- * Input for `stream-broker.subscribeFrames` (Phase 5 / D9). A consumer asks the
6849
- * broker for a `FrameHandle` stream of one `format`; the broker maintains one
6850
- * shared-memory ring per `(brokerId, format)` actually requested, so a `gray`
6851
- * subscriber (motion) and an `rgb` subscriber (detection) each read the format
6852
- * they asked for with no broker-side conversion.
6853
- */
6854
- var SubscribeFramesInputSchema = object({
6855
- brokerId: string(),
6856
- format: FrameHandleFormatSchema,
6857
- /**
6858
- * Optional reader-side cadence hint in frames per second. The broker does
6859
- * NOT throttle — latest-wins ring reads drop frames implicitly for a slow
6860
- * consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
6861
- * the consumer can pace its own `pullFrameHandles` polling.
6862
- */
6863
- maxFps: number().positive().optional(),
6864
- /** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
6865
- tag: string().optional()
6866
- });
6867
- /**
6868
- * Result of `stream-broker.subscribeFrames`. The consumer then polls
6869
- * `pullFrameHandles({ subscriptionId, maxCount })` and feeds each returned
6870
- * `FrameHandle` to a `FrameRingReader`.
6871
- */
6872
- var SubscribeFramesResultSchema = object({
6873
- /** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
6874
- subscriptionId: string(),
6875
- /** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
6876
- maxFps: number().nonnegative()
6877
- });
6878
- /**
6879
6806
  * Wire schema for a decoded audio chunk (Phase 5 / D9). Mirrors the
6880
6807
  * `DecodedAudioChunk` TS interface in `interfaces/stream-broker.ts`: PCM
6881
6808
  * sample bytes plus the track parameters a consumer needs to interpret them.
@@ -6883,8 +6810,8 @@ var SubscribeFramesResultSchema = object({
6883
6810
  * Audio chunks are tiny (a ~500ms AudioCodecSession window is a few KB of
6884
6811
  * Float32 PCM), so unlike video frames they ship their bytes INLINE over
6885
6812
  * tRPC / Moleculer — no shared-memory plane. `data` is typed `Uint8Array`
6886
- * (the wire-serialisable supertype of `Buffer`) to match `DecodedFrameSchema`
6887
- * / `EncodedPacketSchema`'s precedent; a `Buffer` is assignable to it.
6813
+ * (the wire-serialisable supertype of `Buffer`); a `Buffer` is assignable to
6814
+ * it.
6888
6815
  */
6889
6816
  var AudioChunkFormatSchema = _enum(AUDIO_CHUNK_FORMATS);
6890
6817
  var DecodedAudioChunkSchema = object({
@@ -6902,11 +6829,10 @@ var DecodedAudioChunkSchema = object({
6902
6829
  format: AudioChunkFormatSchema.optional()
6903
6830
  });
6904
6831
  /**
6905
- * Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). The
6906
- * handle-free, ship-bytes-inline analogue of `subscribeFrames`: a consumer
6907
- * asks the broker for the decoded audio-chunk stream of one broker; the
6908
- * broker keeps a per-subscription bounded FIFO queue the consumer drains via
6909
- * `pullAudioChunks`.
6832
+ * Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). Audio ships
6833
+ * its bytes inline: a consumer asks the broker for the decoded audio-chunk
6834
+ * stream of one broker; the broker keeps a per-subscription bounded FIFO queue
6835
+ * the consumer drains via `pullAudioChunks`.
6910
6836
  */
6911
6837
  var SubscribeAudioChunksInputSchema = object({
6912
6838
  brokerId: string(),
@@ -6937,9 +6863,7 @@ var BrokerStatsSchema = object({
6937
6863
  "stopped"
6938
6864
  ]),
6939
6865
  inputFps: number(),
6940
- decodeFps: number(),
6941
6866
  encodedSubscribers: number(),
6942
- decodedSubscribers: number(),
6943
6867
  uptimeMs: number(),
6944
6868
  bitrateKbps: number(),
6945
6869
  idrIntervalMs: number(),
@@ -6952,14 +6876,6 @@ var BrokerStatsSchema = object({
6952
6876
  preBufferMs: number(),
6953
6877
  preBufferPackets: number(),
6954
6878
  /**
6955
- * Moleculer node id of the decoder provider currently servicing this
6956
- * stream's decoded subscribers. `null` until the deferred decoder is
6957
- * created (no decoded clients yet, or codec not detected). Surfaces the
6958
- * runtime decoder placement so the UI can show "Decoder: <agent>" without
6959
- * a separate cap call per broker.
6960
- */
6961
- decoderNodeId: string().nullable(),
6962
- /**
6963
6879
  * Detected audio track parameters from the RTSP DESCRIBE / SDP. `null`
6964
6880
  * when the stream has no audio track or the broker is in cold start.
6965
6881
  * `supported = false` means the codec was detected but the local
@@ -10363,70 +10279,6 @@ var StorageLocationDeclarationSchema = object({
10363
10279
  "backup"
10364
10280
  ]).optional()
10365
10281
  });
10366
- var DecoderStatsSchema = object({
10367
- inputFps: number(),
10368
- outputFps: number(),
10369
- avgDecodeTimeMs: number(),
10370
- droppedFrames: number(),
10371
- /**
10372
- * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
10373
- * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
10374
- * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
10375
- * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
10376
- */
10377
- lagMs: number().optional(),
10378
- effectiveFps: number().optional(),
10379
- adaptiveFps: number().optional()
10380
- });
10381
- var DecoderSessionConfigSchema = object({
10382
- codec: string(),
10383
- maxFps: number().default(0),
10384
- outputFormat: _enum([
10385
- "jpeg",
10386
- "rgb",
10387
- "bgr",
10388
- "yuv420",
10389
- "gray"
10390
- ]).default("jpeg"),
10391
- scale: number().default(1),
10392
- width: number().optional(),
10393
- height: number().optional(),
10394
- /**
10395
- * Identifier of the camera this decoder session serves. Optional
10396
- * because the cap is generic (any caller could request decode), but
10397
- * stream-broker passes it so decoder logs include `deviceId` for
10398
- * per-camera filtering when diagnosing failures (e.g. node-av
10399
- * sendPacket errors on a single hung camera).
10400
- */
10401
- deviceId: number().int().nonnegative().optional(),
10402
- /**
10403
- * Free-form tag for log scoping. Stream-broker uses
10404
- * `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
10405
- * on every line so `grep tag=broker:5/high` filters one camera
10406
- * profile cleanly.
10407
- */
10408
- tag: string().optional(),
10409
- /**
10410
- * Where the session delivers decoded frames (Phase 5 / D9):
10411
- *
10412
- * - `'callback'` (default) — the legacy pixel path: decoded frames are
10413
- * buffered as `DecodedFrame`s and drained via `pullFrames`.
10414
- * - `'shm'` — the shared-memory frame plane: decoded frames are written
10415
- * into an OS shared-memory ring and drained as zero-pixel
10416
- * `FrameHandle`s via `pullHandles`. A session is one mode or the
10417
- * other — `pullFrames` returns nothing for an `'shm'` session and
10418
- * `pullHandles` returns nothing for a `'callback'` session.
10419
- */
10420
- frameSink: _enum(["callback", "shm"]).default("callback"),
10421
- /**
10422
- * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
10423
- * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
10424
- * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
10425
- * stream-broker's `streamingDebug` gate — off by default so production logs
10426
- * stay quiet and the emit path pays zero per-frame cost when disabled.
10427
- */
10428
- debug: boolean().optional()
10429
- });
10430
10282
  var EU_DST = {
10431
10283
  offsetHours: 1,
10432
10284
  startMonth: 3,
@@ -11101,57 +10953,26 @@ var ClipSearchStrictnessSchema = _enum([
11101
10953
  "balanced",
11102
10954
  "strict"
11103
10955
  ]);
11104
- new Set([
11105
- {
11106
- id: "person",
11107
- name: "Person"
11108
- },
11109
- {
11110
- id: "vehicle",
11111
- name: "Vehicle"
11112
- },
11113
- {
11114
- id: "animal",
11115
- name: "Animal"
11116
- },
11117
- {
11118
- id: "package",
11119
- name: "Package"
11120
- }
11121
- ].map((l) => l.id));
11122
- var COCO_TO_MACRO = {
11123
- mapping: {
11124
- person: "person",
11125
- bicycle: "vehicle",
11126
- car: "vehicle",
11127
- motorcycle: "vehicle",
11128
- airplane: "vehicle",
11129
- bus: "vehicle",
11130
- train: "vehicle",
11131
- truck: "vehicle",
11132
- boat: "vehicle",
11133
- bird: "animal",
11134
- cat: "animal",
11135
- dog: "animal",
11136
- horse: "animal",
11137
- sheep: "animal",
11138
- cow: "animal",
11139
- elephant: "animal",
11140
- bear: "animal",
11141
- zebra: "animal",
11142
- giraffe: "animal",
11143
- suitcase: "package",
11144
- backpack: "package",
11145
- handbag: "package"
11146
- },
11147
- preserveOriginal: false
11148
- };
11149
- /** Steps a root detector may declare it fills. */
11150
- var FILLABLE_STEP_IDS = [
10956
+ /** Steps whose effect a root label can BE. */
10957
+ var LABEL_SUPPLY_STEP_IDS = [
11151
10958
  "animal-classifier",
11152
10959
  "vehicle-classifier",
11153
10960
  "package-detection"
11154
10961
  ];
10962
+ /** Steps whose box a root detection can BE. */
10963
+ var CROP_SUPPLY_STEP_IDS = ["plate-detection", "face-detection"];
10964
+ /**
10965
+ * Steps whose per-detection MASK a root detection can carry (D737). The live
10966
+ * mask step is `segmentation` — a frame-plane refiner that runs its own model
10967
+ * once per detection crop. (`instance-segmentation` is a dormant step id that
10968
+ * no camera tree carries.)
10969
+ */
10970
+ var MASK_SUPPLY_STEP_IDS = ["segmentation"];
10971
+ [
10972
+ ...LABEL_SUPPLY_STEP_IDS,
10973
+ ...CROP_SUPPLY_STEP_IDS,
10974
+ ...MASK_SUPPLY_STEP_IDS
10975
+ ];
11155
10976
  var MODEL_FORMATS = [
11156
10977
  "onnx",
11157
10978
  "coreml",
@@ -11180,7 +11001,53 @@ var ModelFormatEntrySchema = object({
11180
11001
  /** Multi-file payload (directory members or sibling files). */
11181
11002
  files: array(string()).readonly().optional(),
11182
11003
  /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
11183
- runtimes: array(_enum(["python"])).readonly().optional()
11004
+ runtimes: array(_enum(["python"])).readonly().optional(),
11005
+ /**
11006
+ * Content revision of the artefact, for one hosted OFF the CamStack mirror.
11007
+ * A format on the mirror leaves it unset: its revision (the sha256 of its
11008
+ * weight file) comes from the downloader's generated table, kept in step
11009
+ * with the mirror by `scripts/check-hosted-model-revisions.ts` (D744). A
11010
+ * node records the revision it downloaded next to the file
11011
+ * (`<file>.revision`); a copy with no record or a different one is stale
11012
+ * unless its weight file hashes to the revision, and a stale copy is
11013
+ * downloaded again, the old one serving until the new one is complete. No
11014
+ * revision at all ⇒ a file on disk is current, whatever it holds (D743).
11015
+ */
11016
+ revision: string().min(1).optional()
11017
+ });
11018
+ /**
11019
+ * What a node holds for one (model, format) (D746). `current` is a complete
11020
+ * copy at its catalog revision — exactly what `downloaded: true` means.
11021
+ * `stale` is bytes on disk that are not (yet) proven current under D743/D744:
11022
+ * no or a different revision record, or a missing sibling. `missing` is no
11023
+ * copy. `downloaded` alone folds `stale` into "not downloaded", which hid
11024
+ * reclaimable bytes and a copy about to be replaced.
11025
+ */
11026
+ var ModelOnDiskStateSchema = _enum([
11027
+ "current",
11028
+ "stale",
11029
+ "missing"
11030
+ ]);
11031
+ /**
11032
+ * The numeric precision of one format's BUILD (D746) — reported only when the
11033
+ * build states it (file-name token, an INT8 variant, an EdgeTPU compile, a
11034
+ * CamStack Core ML export). Absent means "not stated", never "fp32".
11035
+ */
11036
+ var ModelFormatPrecisionSchema = _enum([
11037
+ "fp32",
11038
+ "fp16",
11039
+ "int8"
11040
+ ]);
11041
+ /**
11042
+ * One format of one model as a node's `pipelineExecutor.getSchema` reports it.
11043
+ * `onDisk` / `precision` are optional for version skew: a runner that predates
11044
+ * them omits them, and a reader falls back to `downloaded`.
11045
+ */
11046
+ var PipelineModelFormatStatusSchema = object({
11047
+ downloaded: boolean(),
11048
+ sizeMB: number(),
11049
+ onDisk: ModelOnDiskStateSchema.optional(),
11050
+ precision: ModelFormatPrecisionSchema.optional()
11184
11051
  });
11185
11052
  /**
11186
11053
  * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
@@ -11284,12 +11151,46 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
11284
11151
  /** True when the weights or their data forbid commercial use. */
11285
11152
  nonCommercial: boolean().optional()
11286
11153
  }));
11287
- /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
11288
- var FillsClassifierEffectSchema = object({
11289
- stepId: _enum(FILLABLE_STEP_IDS),
11290
- labelToEffect: record(string(), string()),
11291
- uncovered: array(string()).readonly()
11292
- });
11154
+ /**
11155
+ * One step a ROOT detector can supply from its own output (D730) — see
11156
+ * `ModelCatalogEntry.suppliesSteps`.
11157
+ *
11158
+ * - `label`: the root's raw class IS the step's answer. `labelToEffect` maps
11159
+ * the root's label to the step's vocabulary; `uncovered` is the vocabulary
11160
+ * the root cannot produce (shown as unavailable, never a blocker).
11161
+ * - `crop`: the root draws the box the step would have found (`license_plate`
11162
+ * for plate-detection, `face` for face-detection). The box becomes a detail
11163
+ * child of the `parentMacro` detection that contains it — never a track.
11164
+ * - `mask`: the root's decode emits an instance mask with every detection (a
11165
+ * YOLO26-seg root, D737) — the `segmentation` step's result, carried on the
11166
+ * detection in the shape that step produces. Derived from the model's
11167
+ * postprocessor on read, never stored by an import.
11168
+ */
11169
+ var RootStepSupplySchema = discriminatedUnion("kind", [
11170
+ object({
11171
+ kind: literal("label"),
11172
+ stepId: _enum(LABEL_SUPPLY_STEP_IDS),
11173
+ labelToEffect: record(string(), string()),
11174
+ uncovered: array(string()).readonly()
11175
+ }),
11176
+ object({
11177
+ kind: literal("crop"),
11178
+ stepId: _enum(CROP_SUPPLY_STEP_IDS),
11179
+ rootLabels: array(string()).readonly(),
11180
+ parentMacro: _enum(["vehicle", "person"]),
11181
+ childClass: _enum(["plate", "face"]),
11182
+ /**
11183
+ * The root's smaller input side, stamped on read by `rootSuppliesOf` from
11184
+ * the model entry — what a step's `minRootInputPx` gate judges. Never
11185
+ * stored by an import.
11186
+ */
11187
+ rootInputPx: number().int().positive().optional()
11188
+ }),
11189
+ object({
11190
+ kind: literal("mask"),
11191
+ stepId: _enum(MASK_SUPPLY_STEP_IDS)
11192
+ })
11193
+ ]);
11293
11194
  var ModelCatalogEntrySchema = object({
11294
11195
  id: string(),
11295
11196
  name: string(),
@@ -11355,6 +11256,35 @@ var ModelCatalogEntrySchema = object({
11355
11256
  */
11356
11257
  defaultConfidence: number().min(0).max(1).optional(),
11357
11258
  /**
11259
+ * Per-MODEL default of the per-class confidence floors (`minConfidence<Macro>`
11260
+ * on a detector step), keyed by macro class: `{ person: 0.45 }`. A class
11261
+ * absent here runs at the step slider's global default. The same row shape
11262
+ * the floor measurement produces (`model-floors.json`: modelId → floors), so
11263
+ * a measured table is copied in as-is. An operator override is bound to the
11264
+ * model it was made for and does not survive a model change (D738). A custom
11265
+ * / imported model may declare it; without it, the global defaults apply.
11266
+ */
11267
+ defaultClassFloors: record(string(), number().min(0).max(1)).optional(),
11268
+ /**
11269
+ * The inference precision this model's OpenVINO IR needs on an Intel GPU.
11270
+ * Absent ⇒ the device default (f16 on a GPU). Set to `'f32'` for an FP32 IR
11271
+ * that produces invalid output at f16 — measured 2026-10-07 for YOLO26
11272
+ * base IRs (`yolo26s`: 0 true / 146 false positives; `yolo26m*`: NaN
11273
+ * scores) on the Core Ultra iGPU and the N100. Threaded to the pool as
11274
+ * `PoolModelConfig.gpuInferencePrecision`; the pool sets
11275
+ * INFERENCE_PRECISION_HINT on a GPU only. Costs ~60% latency on the GPU.
11276
+ */
11277
+ gpuInferencePrecision: _enum(["f32", "f16"]).optional(),
11278
+ /**
11279
+ * ROOT detectors only: per supplied step (`animal-classifier`, …), the
11280
+ * minimum DETECTION score from which this root's own fine label (species,
11281
+ * vehicle type — D736 root supply) is taken (D741). Below it the detection
11282
+ * keeps its macro class without the fine label. `1` = never take it from
11283
+ * this root. Absent ⇒ no floor beyond the macro floor. The supplied step's
11284
+ * `minConfidence` slider, bound to the ROOT model, overrides it.
11285
+ */
11286
+ suppliedLabelFloors: record(string(), number().min(0).max(1)).optional(),
11287
+ /**
11358
11288
  * When true, the executor produces a landmark-aligned crop (similarity warp
11359
11289
  * onto the canonical template) before this step runs, instead of a plain
11360
11290
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -11416,15 +11346,15 @@ var ModelCatalogEntrySchema = object({
11416
11346
  */
11417
11347
  classMap: DetectionCatalogClassMapSchema.optional(),
11418
11348
  /**
11419
- * The pipeline steps this ROOT detector already does the work of (D715):
11420
- * its labels name the effect the step exists to produce (`deer` for
11421
- * `animal-classifier`, `package` for `package-detection`). Derived from the
11422
- * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
11423
- * declares none. Whether a declaration is honoured is the step's own
11424
- * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
11425
- * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
11349
+ * The pipeline steps this ROOT detector can supply from its own output
11350
+ * (D730): its labels name a step's effect (`deer` for `animal-classifier`)
11351
+ * or draw a step's box (`license_plate` for `plate-detection`). Computed at
11352
+ * import from THIS model's labelmap by `deriveRootSupplies`, never written
11353
+ * by hand and never assumed per family; a row without it is derived on read
11354
+ * (`rootSuppliesOf`). Whether a camera uses it is the step's own
11355
+ * `useRootModel` flag (`resolveRootSupply`).
11426
11356
  */
11427
- fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
11357
+ suppliesSteps: array(RootStepSupplySchema).readonly().optional(),
11428
11358
  /**
11429
11359
  * The model's CLIP feature-space contract (text encoder, dimension, vector
11430
11360
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
@@ -13027,13 +12957,6 @@ var BrokerRtspClientSchema = object({
13027
12957
  lastRtpAt: number(),
13028
12958
  bytesSent: number()
13029
12959
  });
13030
- var BrokerDecodedClientSchema = object({
13031
- tag: string(),
13032
- subscribedAt: number(),
13033
- maxFps: number(),
13034
- framesDelivered: number(),
13035
- framesDropped: number()
13036
- });
13037
12960
  var BrokerAudioClientSchema = object({
13038
12961
  tag: string(),
13039
12962
  subscribedAt: number(),
@@ -13125,7 +13048,6 @@ var BrokerEncodedClientSchema = object({
13125
13048
  });
13126
13049
  var BrokerClientsSchema = object({
13127
13050
  rtsp: array(BrokerRtspClientSchema).readonly(),
13128
- decoded: array(BrokerDecodedClientSchema).readonly(),
13129
13051
  audio: array(BrokerAudioClientSchema).readonly(),
13130
13052
  encoded: array(BrokerEncodedClientSchema).readonly(),
13131
13053
  pipeClients: number(),
@@ -13494,11 +13416,7 @@ method(object({
13494
13416
  auth: "admin"
13495
13417
  }), method(object({ brokerId: string() }), BrokerClientsSchema), method(object({
13496
13418
  brokerId: string(),
13497
- channel: _enum([
13498
- "rtsp",
13499
- "decoded",
13500
- "audio"
13501
- ]),
13419
+ channel: _enum(["rtsp", "audio"]),
13502
13420
  handle: string()
13503
13421
  }), object({ killed: boolean() }), {
13504
13422
  kind: "mutation",
@@ -13533,10 +13451,7 @@ method(object({
13533
13451
  }), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(object({
13534
13452
  subscriptionId: string(),
13535
13453
  maxCount: number().int().positive().default(8)
13536
- }), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(SubscribeFramesInputSchema, SubscribeFramesResultSchema, { kind: "mutation" }), method(object({
13537
- subscriptionId: string(),
13538
- maxCount: number().int().positive().default(4)
13539
- }), array(FrameHandleSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
13454
+ }), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
13540
13455
  brokerId: string(),
13541
13456
  seconds: number().min(0).max(30)
13542
13457
  }), _void(), {
@@ -14795,54 +14710,12 @@ id: union([string(), number()]) }), {
14795
14710
  kind: "mutation",
14796
14711
  auth: "admin"
14797
14712
  });
14798
- /**
14799
- * shm ring usage stats for a `frameSink: 'shm'` decoder session —
14800
- * exposed via `decoder.getShmStats` so downstream consumers can
14801
- * observe ring pressure (slot count, byte budget, hit/miss ratio).
14802
- */
14803
- var ShmRingStatsSchema = object({
14804
- sessionId: string(),
14805
- slotCount: number().int(),
14806
- slotByteLength: number().int(),
14807
- segmentBytes: number().int(),
14808
- budgetMb: number().int(),
14809
- framesWritten: number().int(),
14810
- getFrameHits: number().int(),
14811
- getFrameMisses: number().int()
14812
- });
14813
- method(object({ codec: string() }), boolean()), method(_void(), object({
14713
+ method(_void(), object({
14814
14714
  id: string(),
14815
14715
  name: string(),
14816
- isPullMode: boolean().optional(),
14817
- priority: number().optional(),
14818
14716
  hwaccel: string().optional(),
14819
14717
  probedBestHwaccel: string().optional()
14820
- })), method(DecoderSessionConfigSchema, object({
14821
- sessionId: string(),
14822
- nodeId: string()
14823
- })), method(object({ sessionId: string() }), _void()), method(object({
14824
- sessionId: string(),
14825
- packet: EncodedPacketSchema
14826
- }), _void()), method(object({
14827
- sessionId: string(),
14828
- url: string()
14829
- }), _void()), method(object({
14830
- sessionId: string(),
14831
- maxCount: number().default(1),
14832
- waitMs: number().optional()
14833
- }), array(DecodedFrameSchema)), method(object({
14834
- sessionId: string(),
14835
- maxCount: number().default(1),
14836
- waitMs: number().optional()
14837
- }), array(FrameHandleSchema)), method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()), method(object({
14838
- sessionId: string(),
14839
- config: DecoderSessionConfigSchema.partial()
14840
- }), _void()), method(object({ sessionId: string() }), DecoderStatsSchema), method(_void(), array(object({
14841
- sessionId: string(),
14842
- codec: string(),
14843
- outputFormat: string(),
14844
- createdAtMs: number()
14845
- })).readonly()), method(_void(), object({ backend: string() }), {
14718
+ })), method(_void(), object({ backend: string() }), {
14846
14719
  kind: "mutation",
14847
14720
  auth: "admin"
14848
14721
  });
@@ -15955,6 +15828,10 @@ var DeviceInfoSchema = object({
15955
15828
  isCamera: boolean(),
15956
15829
  /** Current config values — serializable snapshot */
15957
15830
  config: record(string(), unknown()),
15831
+ /** Paths inside `config` the device's schema declares secret (D783) —
15832
+ * what the non-admin redaction withholds. Paths, never values. Absent
15833
+ * when the owning runner has not reported them. */
15834
+ secretConfigPaths: array(string()).optional(),
15958
15835
  /** Hardware + identity blob (manufacturer / model / firmware / sn /
15959
15836
  * uid / mac / …). Populated by drivers; editable via setMetadata. */
15960
15837
  metadata: record(string(), unknown()).nullable().optional(),
@@ -16160,7 +16037,13 @@ var DeviceRegisterPayloadSchema = object({
16160
16037
  * call (workers re-register on init), so probe-driven updates
16161
16038
  * (e.g. PTZ flag flipping after the abilities probe) propagate. */
16162
16039
  features: array(string()).optional(),
16163
- config: record(string(), unknown())
16040
+ config: record(string(), unknown()),
16041
+ /** Config paths the device's own schema DECLARES secret
16042
+ * (`.meta({ secret: true })` — dotted, `[]` for array items, e.g.
16043
+ * `connection.password`). Re-published on every register; the non-admin
16044
+ * redaction withholds them at any depth (D783). Optional: an older runner
16045
+ * omits it and the keyword backstop applies. */
16046
+ secretConfigPaths: array(string()).optional()
16164
16047
  });
16165
16048
  var DeviceRemovePayloadSchema = object({ deviceId: number() });
16166
16049
  var DevicePersistConfigPayloadSchema = object({
@@ -17006,6 +16889,12 @@ method(_void(), array(string()).readonly(), { auth: "admin" }), method(object({
17006
16889
  kind: "mutation",
17007
16890
  auth: "admin"
17008
16891
  });
16892
+ var HUB_ADDRESS_ROLES = [
16893
+ "appConnections",
16894
+ "notificationTaps",
16895
+ "internal",
16896
+ "publicEndpoint"
16897
+ ];
17009
16898
  /**
17010
16899
  * Transport bounds for AI capability methods.
17011
16900
  *
@@ -17853,7 +17742,14 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
17853
17742
  icon: string().optional(),
17854
17743
  /** Addon-owned HTTP route the button navigates to (GET). */
17855
17744
  startUrl: string(),
17856
- stage: LoginStageEnum
17745
+ stage: LoginStageEnum,
17746
+ /**
17747
+ * The provider names an external identity a signed-in user can link to
17748
+ * their own account (D782): `auth.listLinkableProviders` /
17749
+ * `beginExternalLink` offer exactly the redirect methods that set this,
17750
+ * whatever their id. Absent / false — a login button only (magic-link).
17751
+ */
17752
+ linkable: boolean().optional()
17857
17753
  }),
17858
17754
  object({
17859
17755
  kind: literal("widget"),
@@ -18789,6 +18685,51 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
18789
18685
  kind: "mutation",
18790
18686
  auth: "admin"
18791
18687
  });
18688
+ new Set([
18689
+ {
18690
+ id: "person",
18691
+ name: "Person"
18692
+ },
18693
+ {
18694
+ id: "vehicle",
18695
+ name: "Vehicle"
18696
+ },
18697
+ {
18698
+ id: "animal",
18699
+ name: "Animal"
18700
+ },
18701
+ {
18702
+ id: "package",
18703
+ name: "Package"
18704
+ }
18705
+ ].map((l) => l.id));
18706
+ var COCO_TO_MACRO = {
18707
+ mapping: {
18708
+ person: "person",
18709
+ bicycle: "vehicle",
18710
+ car: "vehicle",
18711
+ motorcycle: "vehicle",
18712
+ airplane: "vehicle",
18713
+ bus: "vehicle",
18714
+ train: "vehicle",
18715
+ truck: "vehicle",
18716
+ boat: "vehicle",
18717
+ bird: "animal",
18718
+ cat: "animal",
18719
+ dog: "animal",
18720
+ horse: "animal",
18721
+ sheep: "animal",
18722
+ cow: "animal",
18723
+ elephant: "animal",
18724
+ bear: "animal",
18725
+ zebra: "animal",
18726
+ giraffe: "animal",
18727
+ suitcase: "package",
18728
+ backpack: "package",
18729
+ handbag: "package"
18730
+ },
18731
+ preserveOriginal: false
18732
+ };
18792
18733
  var AUDIO_MACRO_LABELS = [
18793
18734
  {
18794
18735
  id: "speech",
@@ -19584,6 +19525,8 @@ var NcSystemEventKindSchema = _enum([
19584
19525
  "stream-offline",
19585
19526
  "node-online",
19586
19527
  "node-offline",
19528
+ "node-restarting",
19529
+ "node-updating",
19587
19530
  "node-inference-unavailable",
19588
19531
  "detection-blind",
19589
19532
  "addon-crash-loop",
@@ -21189,7 +21132,13 @@ var NcAlarmModeDelaysListSchema = array(object({
21189
21132
  * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
21190
21133
  * is the one that starts the entry delay — the entry-delay notification already names it.
21191
21134
  */
21192
- notifySensorRewatched: boolean().optional()
21135
+ notifySensorRewatched: boolean().optional(),
21136
+ /**
21137
+ * D735: notify "ignored" when a sensor this arm bypassed really MOVED while armed (its own
21138
+ * change time is after the arm) and set nothing off. Absent = false (logged, not sent). A
21139
+ * re-sync, a recovery from `unavailable` or a duplicate is never announced, switch or not.
21140
+ */
21141
+ notifySensorIgnored: boolean().optional()
21193
21142
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21194
21143
  var NcAlarmModeDelaysEditListSchema = array(object({
21195
21144
  mode: AlarmArmModeSchema,
@@ -21202,7 +21151,9 @@ var NcAlarmModeDelaysEditListSchema = array(object({
21202
21151
  /** D706: set the switch, or `null` to clear it (back to the default, false). */
21203
21152
  notifyDuringEntryDelay: boolean().nullable().optional(),
21204
21153
  /** D706: set the switch, or `null` to clear it (back to the default, false). */
21205
- notifySensorRewatched: boolean().nullable().optional()
21154
+ notifySensorRewatched: boolean().nullable().optional(),
21155
+ /** D735: set the switch, or `null` to clear it (back to the default, false). */
21156
+ notifySensorIgnored: boolean().nullable().optional()
21206
21157
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21207
21158
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
21208
21159
  var NcAlarmNonBlockingEditSchema = object({
@@ -22180,8 +22131,8 @@ Object.freeze(Object.fromEntries([{
22180
22131
  var CLUSTER_STEP_SETTING_FIELDS = [{
22181
22132
  stepId: "face-embedding",
22182
22133
  key: "minLandmarkFaceSize",
22183
- label: "Min face size for recognition (detection px)",
22184
- description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
22134
+ label: "Min face size to embed (detection-frame px)",
22135
+ description: "Faces smaller than this in the small frame the detector sees are not embedded, so they can never be recognised. Below it the face cannot be aligned reliably and a bad embedding matches everyone. Same value on every node. 0 = no limit.",
22185
22136
  type: "slider",
22186
22137
  min: 0,
22187
22138
  max: 64,
@@ -23233,7 +23184,13 @@ var RetrainFrameSchema = object({
23233
23184
  sizeBytes: number().int(),
23234
23185
  width: number().int(),
23235
23186
  height: number().int(),
23236
- copiedAt: number()
23187
+ copiedAt: number(),
23188
+ /** When the CAMERA captured the frame. Absent on a copy taken before D785. */
23189
+ capturedAt: number().optional(),
23190
+ /** The operator's "every subject in this frame is boxed". Detector
23191
+ * evaluation keeps only complete frames: an unboxed subject would count as
23192
+ * a false positive. */
23193
+ complete: boolean()
23237
23194
  });
23238
23195
  /** Why a copy-on-select could not be honoured — named, never a silent skip. */
23239
23196
  var RetrainCopyRefusalSchema = _enum([
@@ -23254,6 +23211,51 @@ var RetrainFrameListSchema = object({
23254
23211
  /** What the page pre-selects — the native key frame when one survives. */
23255
23212
  autoPickMediaId: number().int().optional()
23256
23213
  });
23214
+ /**
23215
+ * Which frames an annotated export carries. Every field narrows; an empty
23216
+ * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
23217
+ * list owned by whoever trains (the training orchestrator), so `frameIds` is
23218
+ * the primitive a version export uses; `batchId` re-selects what an earlier
23219
+ * export carried (`exportedInBatch`).
23220
+ */
23221
+ var RetrainExportFilterSchema = object({
23222
+ deviceIds: array(number()).optional(),
23223
+ frameIds: array(string()).max(2e4).optional(),
23224
+ batchId: string().optional(),
23225
+ /** Only frames the operator marked complete (all subjects boxed). */
23226
+ completeOnly: boolean().optional()
23227
+ });
23228
+ /**
23229
+ * `frames`: the full frame copies, boxes in `annotations.json`.
23230
+ * `crops`: additionally one JPEG per subject, cut with the runtime detail-crop
23231
+ * convention — the classifier layout.
23232
+ */
23233
+ var RetrainExportLayoutSchema = _enum(["frames", "crops"]);
23234
+ /**
23235
+ * Where `writeRetrainArchive` streams the tar: one HTTP request whose body is
23236
+ * the archive, sent chunk by chunk. Covers a presigned PUT and a provider
23237
+ * addon's data-plane upload route alike. Headers are sent verbatim and never
23238
+ * logged.
23239
+ */
23240
+ var RetrainArchiveTargetSchema = object({
23241
+ kind: literal("http"),
23242
+ method: _enum(["PUT", "POST"]),
23243
+ url: string().url(),
23244
+ headers: record(string(), string()).optional()
23245
+ });
23246
+ var RetrainArchiveResultSchema = object({
23247
+ batchId: string(),
23248
+ frames: number().int(),
23249
+ crops: number().int(),
23250
+ annotations: number().int(),
23251
+ /** Frames planned but not shipped (unreadable copy, path too long). */
23252
+ missing: number().int(),
23253
+ bytes: number().int(),
23254
+ /** sha256 of the exact bytes sent. */
23255
+ sha256: string(),
23256
+ /** The target's HTTP status. */
23257
+ status: number().int()
23258
+ });
23257
23259
  /** What the operator asked the assist to look for. */
23258
23260
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
23259
23261
  kind: literal("package"),
@@ -24048,9 +24050,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
24048
24050
  }), RetrainTransitionResultSchema, {
24049
24051
  kind: "mutation",
24050
24052
  auth: "admin"
24051
- }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
24053
+ }), method(RetrainExportFilterSchema.extend({ layout: RetrainExportLayoutSchema.optional() }), object({ url: string() }), {
24052
24054
  kind: "query",
24053
24055
  auth: "admin"
24056
+ }), method(object({
24057
+ deviceId: number(),
24058
+ trackId: string(),
24059
+ frameId: string(),
24060
+ complete: boolean()
24061
+ }), RetrainFrameSchema, {
24062
+ kind: "mutation",
24063
+ auth: "admin"
24064
+ }), method(object({
24065
+ filter: RetrainExportFilterSchema,
24066
+ layout: RetrainExportLayoutSchema,
24067
+ target: RetrainArchiveTargetSchema
24068
+ }), RetrainArchiveResultSchema, {
24069
+ kind: "mutation",
24070
+ auth: "admin",
24071
+ timeoutMs: 60 * 6e4
24054
24072
  }), method(object({
24055
24073
  /** Which of the three event tables owns the row. */
24056
24074
  ownerType: EventOwnerTypeSchema,
@@ -24101,6 +24119,34 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
24101
24119
  timestamp: number()
24102
24120
  });
24103
24121
  /**
24122
+ * A root model's boxes standing in for one crop-kind step's own inference
24123
+ * (D730) — see `runPipeline.suppliedRoot`.
24124
+ */
24125
+ var SuppliedRootOutputSchema = object({
24126
+ stepId: string(),
24127
+ /** The root model that drew the boxes — stamped on the result. */
24128
+ modelId: string(),
24129
+ detections: array(object({
24130
+ /** `[x1, y1, x2, y2]` in the pixels of the call's image. */
24131
+ bbox: tuple([
24132
+ number(),
24133
+ number(),
24134
+ number(),
24135
+ number()
24136
+ ]),
24137
+ score: number(),
24138
+ /**
24139
+ * Five facial landmarks in the same pixels — a face the step's own
24140
+ * detector already re-found inside a root face box (D730), so its
24141
+ * embedder child aligns it exactly as it aligns any detected face.
24142
+ */
24143
+ landmarks: array(object({
24144
+ x: number(),
24145
+ y: number()
24146
+ })).optional()
24147
+ })).min(1)
24148
+ });
24149
+ /**
24104
24150
  * Reference to the frame's retained NATIVE surface + the parent crop's placement
24105
24151
  * within the frame, so the executor can re-cut a leaf child ROI at native
24106
24152
  * resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
@@ -24148,7 +24194,7 @@ var FrameRefSchema = object({
24148
24194
  timestamp: number(),
24149
24195
  capturedAt: number().optional()
24150
24196
  });
24151
- var ModelFormatSchema$1 = _enum([
24197
+ var ModelFormatSchema$2 = _enum([
24152
24198
  "onnx",
24153
24199
  "coreml",
24154
24200
  "openvino",
@@ -24166,7 +24212,7 @@ var PipelineSlotSchema = _enum([
24166
24212
  var PipelineEngineChoiceSchema = object({
24167
24213
  runtime: literal("python"),
24168
24214
  backend: string(),
24169
- format: ModelFormatSchema$1,
24215
+ format: ModelFormatSchema$2,
24170
24216
  device: string().optional()
24171
24217
  });
24172
24218
  /**
@@ -24205,33 +24251,15 @@ var PipelineDefaultStepSchema = lazy(() => object({
24205
24251
  group: string().optional(),
24206
24252
  settings: record(string(), unknown()).optional()
24207
24253
  }));
24208
- var PipelineTemplateStepSchema = lazy(() => object({
24209
- addonId: string(),
24210
- enabled: boolean(),
24211
- modelId: string(),
24212
- children: array(PipelineTemplateStepSchema).readonly(),
24213
- settings: record(string(), unknown()).optional()
24214
- }));
24215
- var PipelineTemplateSchema$1 = object({
24216
- id: string(),
24217
- name: string(),
24218
- createdAt: string(),
24219
- updatedAt: string(),
24220
- engine: PipelineEngineChoiceSchema,
24221
- steps: array(PipelineTemplateStepSchema).readonly()
24222
- });
24223
24254
  var PipelineModelOptionSchema = object({
24224
24255
  id: string(),
24225
24256
  name: string(),
24226
- formats: record(string(), object({
24227
- downloaded: boolean(),
24228
- sizeMB: number()
24229
- })),
24257
+ formats: record(string(), PipelineModelFormatStatusSchema),
24230
24258
  group: ModelVariantGroupSchema.optional(),
24231
24259
  legacy: boolean().optional(),
24232
24260
  provider: ModelProviderIdSchema.optional(),
24233
24261
  defaultConfidence: number().optional(),
24234
- fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
24262
+ suppliesSteps: array(RootStepSupplySchema).readonly().optional()
24235
24263
  });
24236
24264
  var ConfigFieldBridge = custom();
24237
24265
  var PipelineAddonSchemaSchema = object({
@@ -24393,6 +24421,22 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
24393
24421
  }), {
24394
24422
  kind: "mutation",
24395
24423
  auth: "admin"
24424
+ }), method(object({
24425
+ nodeId: string(),
24426
+ deviceIds: array(number()).readonly().optional(),
24427
+ dryRun: boolean()
24428
+ }), object({
24429
+ entries: array(object({
24430
+ deviceId: number(),
24431
+ keys: array(string()).readonly()
24432
+ })).readonly(),
24433
+ refused: array(object({
24434
+ deviceId: number(),
24435
+ reason: string()
24436
+ })).readonly()
24437
+ }), {
24438
+ kind: "mutation",
24439
+ auth: "admin"
24396
24440
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
24397
24441
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
24398
24442
  deviceKey: string(),
@@ -24418,22 +24462,14 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
24418
24462
  }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
24419
24463
  steps: array(PipelineStepInputSchema),
24420
24464
  deviceKey: string().optional()
24421
- }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
24422
- name: string(),
24423
- steps: array(PipelineTemplateStepSchema).readonly(),
24424
- engine: PipelineEngineChoiceSchema
24425
- }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
24426
- id: string(),
24427
- name: string().optional(),
24428
- steps: array(PipelineTemplateStepSchema).readonly().optional()
24429
- }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
24465
+ }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
24430
24466
  addonId: string(),
24431
24467
  modelId: string(),
24432
- format: ModelFormatSchema$1
24468
+ format: ModelFormatSchema$2
24433
24469
  }), DownloadModelResultSchema, { kind: "mutation" }), method(object({
24434
24470
  addonId: string(),
24435
24471
  modelId: string(),
24436
- format: ModelFormatSchema$1
24472
+ format: ModelFormatSchema$2
24437
24473
  }), object({ success: literal(true) }), { kind: "mutation" }), method(object({
24438
24474
  steps: array(PipelineStepInputSchema).min(1),
24439
24475
  frame: FrameInputSchema.optional(),
@@ -24499,7 +24535,16 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
24499
24535
  * `device-not-servable`), and nothing reaches the camera's live
24500
24536
  * trace stream. Absent ⇒ unchanged behaviour.
24501
24537
  */
24502
- replay: literal(true).optional()
24538
+ replay: literal(true).optional(),
24539
+ /**
24540
+ * Root-supplied detections for the tree's ROOT step (D730). Set by
24541
+ * `runDetailSubtree` when the camera's root model supplies a crop-kind
24542
+ * step (a Frigate+ `license_plate` for `plate-detection`): the step is
24543
+ * NOT inferred, these boxes are its output, and its children (the plate
24544
+ * reader) run on them through their own crop policy. Boxes are in the
24545
+ * PIXELS of the image this call carries. Absent ⇒ the root step runs.
24546
+ */
24547
+ suppliedRoot: SuppliedRootOutputSchema.optional()
24503
24548
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
24504
24549
  steps: array(PipelineStepInputSchema).min(1),
24505
24550
  frames: array(FrameInputSchema).min(1).max(255),
@@ -24581,6 +24626,375 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
24581
24626
  filename: string().optional(),
24582
24627
  settings: record(string(), unknown()).optional()
24583
24628
  }), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
24629
+ /**
24630
+ * The wire shapes of the Auto tune plan and apply (D745), used by the
24631
+ * `pipeline-orchestrator` cap. The recommender's own types
24632
+ * (`recommend.ts`) are the TS face of the same data; these
24633
+ * schemas are what crosses the cap boundary.
24634
+ */
24635
+ var ModelFormatSchema$1 = _enum(MODEL_FORMATS);
24636
+ /** The operator's range for it. */
24637
+ var MIN_SESSIONS_PER_DEVICE_RANGE = {
24638
+ min: 1,
24639
+ max: 8
24640
+ };
24641
+ var HardwareClassIdSchema = _enum([
24642
+ "intel-core-ultra",
24643
+ "intel-n-series",
24644
+ "apple-m-base",
24645
+ "apple-m-pro",
24646
+ "unknown"
24647
+ ]);
24648
+ var AcceleratorKindSchema = _enum([
24649
+ "intel-npu",
24650
+ "intel-igpu",
24651
+ "x86-cpu",
24652
+ "arm-cpu",
24653
+ "apple-ane",
24654
+ "coral"
24655
+ ]);
24656
+ var RecommendationReasonSchema = discriminatedUnion("kind", [
24657
+ object({
24658
+ kind: literal("capacity"),
24659
+ sessions: number(),
24660
+ minSessions: number()
24661
+ }),
24662
+ object({
24663
+ kind: literal("tie-faster"),
24664
+ over: string(),
24665
+ recallDelta: number()
24666
+ }),
24667
+ object({
24668
+ kind: literal("stepped-down"),
24669
+ from: string(),
24670
+ to: string(),
24671
+ limitedBy: string()
24672
+ }),
24673
+ object({
24674
+ kind: literal("no-fit-lightest"),
24675
+ sessions: number(),
24676
+ minSessions: number()
24677
+ }),
24678
+ object({
24679
+ kind: literal("derived-latency"),
24680
+ modelId: string()
24681
+ }),
24682
+ object({ kind: literal("cpu-device") }),
24683
+ object({ kind: literal("coral-untouched") }),
24684
+ object({ kind: literal("device-disabled") }),
24685
+ object({ kind: literal("device-unavailable") }),
24686
+ object({ kind: literal("node-offline") }),
24687
+ object({ kind: literal("no-hardware-facts") }),
24688
+ object({
24689
+ kind: literal("no-measured-data"),
24690
+ hardwareClass: HardwareClassIdSchema
24691
+ }),
24692
+ object({
24693
+ kind: literal("no-family-build"),
24694
+ format: ModelFormatSchema$1
24695
+ })
24696
+ ]);
24697
+ var DeviceModelChoiceSchema = object({
24698
+ modelId: string(),
24699
+ p50Ms: number(),
24700
+ fps: number(),
24701
+ measured: boolean(),
24702
+ /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
24703
+ capacitySessions: number(),
24704
+ personRecall: number()
24705
+ });
24706
+ var DeviceRecommendationSchema = object({
24707
+ deviceKey: string(),
24708
+ accelerator: AcceleratorKindSchema.nullable(),
24709
+ enabled: boolean(),
24710
+ available: boolean(),
24711
+ chosen: DeviceModelChoiceSchema.nullable(),
24712
+ reasons: array(RecommendationReasonSchema).readonly()
24713
+ });
24714
+ var NodeRecommendationSchema = object({
24715
+ nodeId: string(),
24716
+ reachable: boolean(),
24717
+ hardwareClass: HardwareClassIdSchema.nullable(),
24718
+ cpuModel: string().nullable(),
24719
+ skipped: boolean(),
24720
+ acceleratorModelId: string().nullable(),
24721
+ devices: array(DeviceRecommendationSchema).readonly(),
24722
+ reasons: array(RecommendationReasonSchema).readonly()
24723
+ });
24724
+ var ModelPinChangeSchema = object({
24725
+ stepId: string(),
24726
+ before: string().nullable(),
24727
+ after: string().nullable()
24728
+ });
24729
+ var NodeDeviceChangeSchema = object({
24730
+ nodeId: string(),
24731
+ deviceKey: string(),
24732
+ madeExplicit: boolean(),
24733
+ modelPins: array(ModelPinChangeSchema).readonly(),
24734
+ thresholds: array(object({
24735
+ stepId: string(),
24736
+ keys: array(string()).readonly()
24737
+ })).readonly()
24738
+ });
24739
+ var CameraOverrideClearSchema = object({
24740
+ deviceId: number(),
24741
+ source: _enum(["step-override", "wholesale"]),
24742
+ nodeId: string(),
24743
+ deviceKey: string().nullable(),
24744
+ stepId: string(),
24745
+ modelIdBefore: string().nullable(),
24746
+ keys: array(string()).readonly()
24747
+ });
24748
+ var DetectorStoreClearSchema = object({
24749
+ deviceId: number(),
24750
+ keys: array(string()).readonly()
24751
+ });
24752
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [
24753
+ object({
24754
+ kind: literal("detector-store-cluster-wide"),
24755
+ skippedNodes: array(string()).readonly()
24756
+ }),
24757
+ object({
24758
+ kind: literal("detector-store-unreadable"),
24759
+ error: string()
24760
+ }),
24761
+ object({
24762
+ kind: literal("coral-enabled"),
24763
+ nodeId: string(),
24764
+ deviceKey: string()
24765
+ })
24766
+ ]);
24767
+ var AutoTuneOptionsSchema = object({
24768
+ /** Share of each accelerator's throughput kept free (0.3–0.5). */
24769
+ headroom: number().min(.3).max(.5).default(.4),
24770
+ /**
24771
+ * The least number of parallel sessions every device must sustain at the
24772
+ * camera rate with the headroom kept free (D755). The most accurate model
24773
+ * that reaches it wins.
24774
+ */
24775
+ minSessionsPerDevice: number().int().min(MIN_SESSIONS_PER_DEVICE_RANGE.min).max(MIN_SESSIONS_PER_DEVICE_RANGE.max).default(2)
24776
+ });
24777
+ var AutoTunePlanSchema = object({
24778
+ /** Hash of everything the apply will write — the apply refuses a different one. */
24779
+ planHash: string(),
24780
+ family: literal("yolov9"),
24781
+ headroom: number(),
24782
+ minSessionsPerDevice: number(),
24783
+ /** The detection rate a session is counted at (the fastest camera running the pipeline root). */
24784
+ cameraFps: number(),
24785
+ generatedAt: number(),
24786
+ nodes: array(NodeRecommendationSchema).readonly(),
24787
+ nodeChanges: array(NodeDeviceChangeSchema).readonly(),
24788
+ cameraClears: array(CameraOverrideClearSchema).readonly(),
24789
+ detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
24790
+ warnings: array(AutoTuneWarningSchema).readonly()
24791
+ });
24792
+ var AutoTuneApplyInputSchema = object({
24793
+ planHash: string(),
24794
+ headroom: number().min(.3).max(.5).default(.4),
24795
+ minSessionsPerDevice: number().int().min(MIN_SESSIONS_PER_DEVICE_RANGE.min).max(MIN_SESSIONS_PER_DEVICE_RANGE.max).default(2)
24796
+ });
24797
+ var AutoTunePhaseResultSchema = object({
24798
+ phase: _enum([
24799
+ "download",
24800
+ "camera-overrides",
24801
+ "detector-thresholds",
24802
+ "node-models",
24803
+ "redispatch"
24804
+ ]),
24805
+ ok: boolean(),
24806
+ detail: string()
24807
+ });
24808
+ var AutoTuneApplyResultSchema = discriminatedUnion("kind", [
24809
+ object({
24810
+ kind: literal("applied"),
24811
+ planHash: string(),
24812
+ phases: array(AutoTunePhaseResultSchema).readonly()
24813
+ }),
24814
+ object({
24815
+ kind: literal("aborted"),
24816
+ phases: array(AutoTunePhaseResultSchema).readonly()
24817
+ }),
24818
+ object({
24819
+ kind: literal("stale"),
24820
+ plan: AutoTunePlanSchema
24821
+ }),
24822
+ object({
24823
+ kind: literal("refused"),
24824
+ reason: _enum(["apply-in-progress"])
24825
+ })
24826
+ ]);
24827
+ /**
24828
+ * Wire shapes of the Load balancing surface (D748): the session placement
24829
+ * policy, the atomic share write, the observed placement statistics, the
24830
+ * hardware share suggestion and the stale device pins.
24831
+ */
24832
+ /**
24833
+ * How a new detection session picks its node and device.
24834
+ * - `least-loaded` — the historical rule: lowest `attached / weight`, a
24835
+ * constant node order at a tie (D37). An idle node always ties at 0, so a
24836
+ * weight only bites once a node already holds a session.
24837
+ * - `share` — the share of PARALLEL sessions is held to the weights, and a
24838
+ * full or drowning node yields to a free one (D748).
24839
+ */
24840
+ var SessionPlacementPolicySchema = _enum(["least-loaded", "share"]);
24841
+ var LoadBalancingSharesInputSchema = object({
24842
+ /** nodeId → share (> 0). A node left out keeps its weight. */
24843
+ nodes: record(string(), number().positive()).default({}),
24844
+ /** nodeId → deviceKey → share (> 0). A device left out keeps its weight. */
24845
+ devices: record(string(), record(string(), number().positive())).default({})
24846
+ });
24847
+ var PlacementStatsInputSchema = object({
24848
+ /** Window the observed shares are averaged over (default 1 h, max 24 h). */
24849
+ windowMs: number().int().min(6e4).max(1440 * 60 * 1e3).default(3600 * 1e3) });
24850
+ var PlacementDeviceStatsSchema = object({
24851
+ deviceKey: string(),
24852
+ /** Sessions running on this device now. */
24853
+ sessionsNow: number(),
24854
+ /** Sessions started on this device inside the window. */
24855
+ sessionsStarted: number(),
24856
+ /** Time-weighted share of the node's parallel sessions over the window (0–1); null = no session ran. */
24857
+ observedShare: number().nullable()
24858
+ });
24859
+ var PlacementNodeStatsSchema = object({
24860
+ nodeId: string(),
24861
+ sessionsNow: number(),
24862
+ sessionsStarted: number(),
24863
+ /** Time-weighted share of the cluster's parallel sessions over the window (0–1); null = none ran. */
24864
+ observedShare: number().nullable(),
24865
+ /** Most sessions this node ran at once inside the window. */
24866
+ peakSessions: number(),
24867
+ /** Sessions a share election handed elsewhere because this node was full or drowning. */
24868
+ yieldsAway: number(),
24869
+ devices: array(PlacementDeviceStatsSchema).readonly()
24870
+ });
24871
+ /** A camera's device pin that the session path cannot honour. */
24872
+ var StaleDevicePinSchema = object({
24873
+ deviceId: number(),
24874
+ deviceKey: string(),
24875
+ /** `disabled` — the key exists on some node but is not enabled anywhere; `absent` — no node has it. */
24876
+ reason: _enum(["disabled", "absent"])
24877
+ });
24878
+ var PlacementStatsSchema = object({
24879
+ policy: SessionPlacementPolicySchema,
24880
+ windowMs: number(),
24881
+ /** How much of the window was actually observed (the hub keeps it in memory). */
24882
+ observedForMs: number(),
24883
+ sessionsNow: number(),
24884
+ /** Most parallel sessions across the cluster inside the window. */
24885
+ clusterPeakSessions: number(),
24886
+ nodes: array(PlacementNodeStatsSchema).readonly(),
24887
+ stalePins: array(StaleDevicePinSchema).readonly()
24888
+ });
24889
+ /**
24890
+ * Where an automatic share's capacity comes from (D755).
24891
+ * - `hardware` — the static capacity of each device at its Auto tune model:
24892
+ * the measured latency table for the node's hardware class.
24893
+ * - `benchmark` — the node's own measured capacity (node benchmark results).
24894
+ * A node with no results falls back to `hardware`, and says so.
24895
+ */
24896
+ var CapacitySourceSchema = _enum(["hardware", "benchmark"]);
24897
+ /** Why a node under the `benchmark` source was sized from hardware instead. */
24898
+ var CapacityFallbackSchema = _enum(["no-benchmark-results", "partial-benchmark-results"]);
24899
+ var SuggestSharesInputSchema = object({
24900
+ headroom: number().min(.3).max(.5).default(.4),
24901
+ /** Default `hardware`. */
24902
+ source: CapacitySourceSchema.default("hardware")
24903
+ });
24904
+ var SuggestedDeviceShareSchema = object({
24905
+ deviceKey: string(),
24906
+ /** Share of the node (0–100, rounded). */
24907
+ share: number(),
24908
+ modelId: string().nullable(),
24909
+ /** Inferences per second at that model, from the measured table; null when sized by a benchmark. */
24910
+ fps: number().nullable(),
24911
+ /** False for a table cell derived from another chip; true for a measured cell or a benchmark. */
24912
+ measured: boolean(),
24913
+ /**
24914
+ * Advisory session cap: ⌊fps × (1 − headroom) / camera fps⌋ from the table,
24915
+ * or the benchmark's measured max sessions. Never enforced.
24916
+ */
24917
+ suggestedMaxSessions: number().nullable()
24918
+ });
24919
+ var SuggestedNodeShareSchema = object({
24920
+ nodeId: string(),
24921
+ /** Share of the cluster (0–100, rounded); null = node skipped (offline, unknown hardware). */
24922
+ share: number().nullable(),
24923
+ /** Parallel sessions the node sustains at the suggested models with the headroom kept free. */
24924
+ capacitySessions: number(),
24925
+ devices: array(SuggestedDeviceShareSchema).readonly(),
24926
+ skippedReason: string().nullable(),
24927
+ /** What this node's capacity was read from; null when the node is skipped. */
24928
+ capacitySource: CapacitySourceSchema.nullable(),
24929
+ /** Set when the `benchmark` source was asked for and this node used `hardware`. */
24930
+ capacityFallback: CapacityFallbackSchema.nullable()
24931
+ });
24932
+ var SuggestSharesResultSchema = object({
24933
+ headroom: number(),
24934
+ /** The source asked for; each node says what it actually used. */
24935
+ source: CapacitySourceSchema,
24936
+ /** Camera detection rate the capacity is counted in (the fastest camera's fps). */
24937
+ cameraFps: number(),
24938
+ /** The Auto tune capacity floor the models were picked at. */
24939
+ minSessionsPerDevice: number(),
24940
+ nodes: array(SuggestedNodeShareSchema).readonly()
24941
+ });
24942
+ /**
24943
+ * Where the node and device shares come from (D750, D755).
24944
+ * - `hardware` (default) — computed by the system from each node's static
24945
+ * capacity (its accelerators at their Auto tune models, from the measured
24946
+ * latency table), recomputed whenever a node or device joins, leaves, is
24947
+ * switched on or off, or changes model. No load input.
24948
+ * - `benchmark` — the same, from each node's measured capacity (node
24949
+ * benchmark results); a node without results falls back to `hardware`.
24950
+ * - `manual` — the operator's stored sliders.
24951
+ * Either way a node or device that cannot take sessions gives its share to
24952
+ * the others in proportion; the stored values are never rewritten for that.
24953
+ */
24954
+ var ShareSourceSchema = _enum([
24955
+ "hardware",
24956
+ "benchmark",
24957
+ "manual"
24958
+ ]);
24959
+ var SetShareSourceInputSchema = object({ source: ShareSourceSchema });
24960
+ object({
24961
+ nodes: record(string(), number()),
24962
+ devices: record(string(), record(string(), number()))
24963
+ });
24964
+ var EffectiveDeviceShareSchema = object({
24965
+ deviceKey: string(),
24966
+ /** Can take sessions now (enabled, available, can run the root). */
24967
+ eligible: boolean(),
24968
+ /** The share the source assigns, as a percentage of the node's devices. */
24969
+ configuredPct: number(),
24970
+ /** The share actually used, after an ineligible device's share went to the others. */
24971
+ effectivePct: number()
24972
+ });
24973
+ var EffectiveNodeShareSchema = object({
24974
+ nodeId: string(),
24975
+ eligible: boolean(),
24976
+ configuredPct: number(),
24977
+ effectivePct: number(),
24978
+ /** Automatic sources: what this node's share was computed from; null under `manual` or before the first answer. */
24979
+ capacitySource: CapacitySourceSchema.nullable(),
24980
+ /** Automatic `benchmark`: why this node used `hardware` instead. */
24981
+ capacityFallback: CapacityFallbackSchema.nullable(),
24982
+ devices: array(EffectiveDeviceShareSchema).readonly()
24983
+ });
24984
+ var EffectiveSharesSchema = object({
24985
+ source: ShareSourceSchema,
24986
+ policy: SessionPlacementPolicySchema,
24987
+ /** An automatic source with no computed answer yet: the stored sliders are used meanwhile. */
24988
+ autoPending: boolean(),
24989
+ /** When the automatic shares were last computed (ms epoch); null = never. */
24990
+ computedAt: number().nullable(),
24991
+ /** What made the system recompute them last. */
24992
+ trigger: string().nullable(),
24993
+ nodes: array(EffectiveNodeShareSchema).readonly(),
24994
+ /** The relative weights the election reads (before eligibility). */
24995
+ nodeWeights: record(string(), number()),
24996
+ deviceWeights: record(string(), record(string(), number()))
24997
+ });
24584
24998
  object({
24585
24999
  activeCameras: number(),
24586
25000
  throttledCameras: number(),
@@ -25498,14 +25912,15 @@ var RunnerLocalLoadSchema = object({
25498
25912
  * Per-inference-device live load (multi-device C4). One entry per deviceKey
25499
25913
  * this runner currently has attached cameras on, so the orchestrator's second
25500
25914
  * `balance()` pass (over a node's devices) weights on real per-pool session
25501
- * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
25502
- * per device is 0 until the pool backlog gets a public accessor (follow-up).
25915
+ * counts. Empty on single-device / pre-multi-device runners. There is no
25916
+ * per-device queue depth: the inference pool's backlog has no accessor, and
25917
+ * a field that always read 0 was removed rather than shown as a measurement
25918
+ * (D762).
25503
25919
  */
25504
25920
  devices: array(object({
25505
25921
  deviceKey: string(),
25506
25922
  backend: string(),
25507
- attachedCameras: number(),
25508
- queueDepthTotal: number()
25923
+ attachedCameras: number()
25509
25924
  })).default([]),
25510
25925
  /** Hardware capability flags reported by this node. */
25511
25926
  hardware: object({
@@ -25641,7 +26056,22 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
25641
26056
  */
25642
26057
  cropJpeg: string().optional(),
25643
26058
  parent: DetailParentSchema,
25644
- steps: array(string()).optional()
26059
+ steps: array(string()).optional(),
26060
+ /**
26061
+ * The camera's root model already drew this step's boxes (D730): a
26062
+ * `license_plate` inside the parent vehicle. The named step is NOT
26063
+ * inferred — these FRAME-space boxes are its output — and its
26064
+ * requested children (the plate reader) run on them. Absent ⇒ every
26065
+ * requested step infers as before.
26066
+ */
26067
+ supplied: object({
26068
+ stepId: string(),
26069
+ modelId: string(),
26070
+ boxes: array(object({
26071
+ bbox: NativeCropBboxSchema,
26072
+ score: number()
26073
+ })).min(1)
26074
+ }).optional()
25645
26075
  }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" }), method(object({
25646
26076
  /** Catalog step id, e.g. `clip-embedding`. */
25647
26077
  stepId: string(),
@@ -25704,14 +26134,6 @@ var CameraPipelineConfigSchema = object({
25704
26134
  settings: record(string(), unknown()).readonly().optional()
25705
26135
  }).nullable().optional()
25706
26136
  });
25707
- var PipelineTemplateSchema = object({
25708
- id: string(),
25709
- name: string(),
25710
- description: string().optional(),
25711
- config: CameraPipelineConfigSchema,
25712
- createdAt: string(),
25713
- updatedAt: string()
25714
- });
25715
26137
  var DeviceStepConfigSchema = object({
25716
26138
  modelId: string().optional(),
25717
26139
  settings: record(string(), unknown()).optional(),
@@ -25785,9 +26207,10 @@ var CameraStepOverridePatchSchema = object({
25785
26207
  modelId: string().optional(),
25786
26208
  settings: record(string(), unknown()).readonly().optional()
25787
26209
  });
26210
+ var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
25788
26211
  var CameraPipelineSettingsSchema = object({
25789
- pinnedAgentNodeId: string().optional(),
25790
26212
  stepToggles: record(string(), boolean()).optional(),
26213
+ stepSettings: CameraStepSettingsSchema.optional(),
25791
26214
  stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
25792
26215
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
25793
26216
  });
@@ -25820,7 +26243,10 @@ var PipelineAssignmentSchema = object({
25820
26243
  });
25821
26244
  /**
25822
26245
  * Per-agent load summary surfaced to the load balancer + dashboards.
25823
- * Aggregated from each runner's `getLocalLoad` cap call.
26246
+ * Aggregated from each runner's `getLocalLoad` cap call. In the
26247
+ * `getAgentLoad` report, a single-device node's default-pool sessions (no
26248
+ * `deviceKey`) are credited to its one eligible device in `load.devices` —
26249
+ * the default pool IS that device (D745); the balancer's census stays raw.
25824
26250
  */
25825
26251
  var AgentLoadSummarySchema = object({
25826
26252
  nodeId: string(),
@@ -25909,26 +26335,27 @@ var CameraBrokerStatusSchema = object({
25909
26335
  width: number(),
25910
26336
  height: number(),
25911
26337
  subscribers: number(),
25912
- inFps: number(),
25913
- outFps: number()
26338
+ /**
26339
+ * Encoded packets/s the broker receives from the camera. null when the
26340
+ * broker's stats read failed — unknown, never 0 (a 0 here reads as a stall).
26341
+ * There is no output rate: decoding runs in the session decode workers, not
26342
+ * in the broker, so the broker's own decoded-frame rate is 0 on every live
26343
+ * camera and is not served (D758).
26344
+ */
26345
+ inFps: number().nullable()
25914
26346
  })).readonly(),
25915
26347
  webrtcSessions: number(),
25916
26348
  rtspRestream: boolean()
25917
26349
  });
25918
- /** Shared-memory ring statistics within the decoder block. */
25919
- var CameraDecoderShmSchema = object({
25920
- framesWritten: number(),
25921
- getFrameHits: number(),
25922
- getFrameMisses: number(),
25923
- budgetMb: number()
25924
- });
25925
- /** Decoder block — null when the decoder stage is unreachable or inactive. */
25926
- var CameraDecoderStatusSchema = object({
25927
- nodeId: string(),
25928
- formats: array(string()).readonly(),
25929
- sessionCount: number(),
25930
- shm: CameraDecoderShmSchema
25931
- });
26350
+ /**
26351
+ * Decoder block — WHERE decode runs (co-located with the detection node by
26352
+ * construction); null when the camera has no detection node. It carries no
26353
+ * frame counter: the shared-memory plane whose counters it used to serve is
26354
+ * gone, and those fields read 0 forever. Whether frames actually flow is read
26355
+ * from `detection.actualFps` (frames delivered to and processed by the
26356
+ * detector), never from a counter nothing feeds.
26357
+ */
26358
+ var CameraDecoderStatusSchema = object({ nodeId: string() });
25932
26359
  /** Motion block — null when motion detection is not active for this device. */
25933
26360
  var CameraMotionStatusSchema = object({
25934
26361
  enabled: boolean(),
@@ -26285,12 +26712,6 @@ method(object({
26285
26712
  }), object({ success: literal(true) }), {
26286
26713
  kind: "mutation",
26287
26714
  auth: "admin"
26288
- }), method(object({
26289
- agentNodeId: string(),
26290
- detectWeight: number().positive().nullable()
26291
- }), object({ success: literal(true) }), {
26292
- kind: "mutation",
26293
- auth: "admin"
26294
26715
  }), method(object({
26295
26716
  agentNodeId: string(),
26296
26717
  detect: boolean().nullable().optional(),
@@ -26332,6 +26753,15 @@ method(object({
26332
26753
  }), {
26333
26754
  kind: "mutation",
26334
26755
  auth: "admin"
26756
+ }), method(AutoTuneOptionsSchema, AutoTunePlanSchema, { auth: "admin" }), method(AutoTuneApplyInputSchema, AutoTuneApplyResultSchema, {
26757
+ kind: "mutation",
26758
+ auth: "admin"
26759
+ }), method(LoadBalancingSharesInputSchema, object({ success: literal(true) }), {
26760
+ kind: "mutation",
26761
+ auth: "admin"
26762
+ }), method(PlacementStatsInputSchema, PlacementStatsSchema, { auth: "admin" }), method(SuggestSharesInputSchema, SuggestSharesResultSchema, { auth: "admin" }), method(_void(), EffectiveSharesSchema, { auth: "admin" }), method(SetShareSourceInputSchema, object({ success: literal(true) }), {
26763
+ kind: "mutation",
26764
+ auth: "admin"
26335
26765
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
26336
26766
  deviceId: number(),
26337
26767
  addonId: string(),
@@ -26348,6 +26778,13 @@ method(object({
26348
26778
  }), object({ success: literal(true) }), {
26349
26779
  kind: "mutation",
26350
26780
  auth: "admin"
26781
+ }), method(object({
26782
+ deviceId: number(),
26783
+ addonId: string(),
26784
+ settings: record(string(), unknown()).nullable()
26785
+ }), object({ success: literal(true) }), {
26786
+ kind: "mutation",
26787
+ auth: "admin"
26351
26788
  }), method(object({
26352
26789
  deviceId: number(),
26353
26790
  agentNodeId: string(),
@@ -26371,25 +26808,7 @@ method(object({
26371
26808
  }), method(_void(), DiskReconcileJobSchema, {
26372
26809
  kind: "mutation",
26373
26810
  auth: "admin"
26374
- }), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
26375
- name: string(),
26376
- description: string().optional(),
26377
- config: CameraPipelineConfigSchema
26378
- }), PipelineTemplateSchema, {
26379
- kind: "mutation",
26380
- auth: "admin"
26381
- }), method(object({
26382
- id: string(),
26383
- name: string().optional(),
26384
- description: string().optional(),
26385
- config: CameraPipelineConfigSchema.optional()
26386
- }), PipelineTemplateSchema, {
26387
- kind: "mutation",
26388
- auth: "admin"
26389
- }), method(object({ id: string() }), object({ success: literal(true) }), {
26390
- kind: "mutation",
26391
- auth: "admin"
26392
- });
26811
+ }), method(_void(), DiskReconcileJobSchema, { auth: "admin" });
26393
26812
  /**
26394
26813
  * Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
26395
26814
  * `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
@@ -27083,7 +27502,19 @@ var SsoBridgeClaimsSchema = object({
27083
27502
  * editing a descriptor must not retroactively extend or shorten a link the
27084
27503
  * operator already consented to.
27085
27504
  */
27086
- refreshTtl: union([number().int().positive(), literal("never")]).optional()
27505
+ refreshTtl: union([number().int().positive(), literal("never")]).optional(),
27506
+ /**
27507
+ * Opaque handle of a hub-side LINK intent (D782). Set by an OIDC callback
27508
+ * that was started from a signed-in user's "Link" button: the finish then
27509
+ * links this identity to the intent's user instead of signing anyone in.
27510
+ * The handle carries no user id — the hub resolves it, single-use.
27511
+ */
27512
+ linkIntent: string().optional(),
27513
+ /**
27514
+ * Verified `iss` of the id_token behind an OIDC login bridge (D782). A
27515
+ * subject is unique only per issuer, so a link is bound to it.
27516
+ */
27517
+ issuer: string().optional()
27087
27518
  });
27088
27519
  method(object({
27089
27520
  claims: SsoBridgeClaimsSchema,
@@ -29160,8 +29591,6 @@ var WebrtcStreamChoiceSchema = object({
29160
29591
  ]).nullable(),
29161
29592
  /** Input FPS from the camera (null for adaptive). */
29162
29593
  inputFps: number().nullable(),
29163
- /** Decoded FPS (null for adaptive). */
29164
- decodeFps: number().nullable(),
29165
29594
  /** Bitrate in kbps (null for adaptive). */
29166
29595
  bitrateKbps: number().nullable()
29167
29596
  });
@@ -29438,7 +29867,22 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
29438
29867
  * field their hints were silently stripped by the schema and the
29439
29868
  * adaptive ladder started blind on the client's display size.
29440
29869
  */
29441
- hints: webrtcClientHintsSchema.optional()
29870
+ hints: webrtcClientHintsSchema.optional(),
29871
+ /**
29872
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
29873
+ * through the `intercom` cap's push-talk triple. When `true` and the
29874
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
29875
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
29876
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
29877
+ *
29878
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
29879
+ * with `intercom`, when the linked user may control that camera. The
29880
+ * hub STRIPS it from every request-bound call (a browser), exactly as
29881
+ * it overwrites `relayOnly` — a viewer's talk permission is the
29882
+ * intercom cap's own surface (share tokens gate it there), and this
29883
+ * flag must not become a second door to the camera's speaker.
29884
+ */
29885
+ talkback: boolean().optional()
29442
29886
  }), object({
29443
29887
  sessionId: string(),
29444
29888
  sdpAnswer: string()
@@ -29493,6 +29937,14 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
29493
29937
  */
29494
29938
  alive: boolean()
29495
29939
  })), method(object({
29940
+ deviceId: number().int().nonnegative(),
29941
+ sessionId: string(),
29942
+ downlinkMbps: number().nonnegative()
29943
+ }), object({
29944
+ outcome: _enum(["switching", "held"]),
29945
+ tier: CamProfileSchema.nullable(),
29946
+ reason: string()
29947
+ }), { kind: "mutation" }), method(object({
29496
29948
  deviceId: number().int().nonnegative(),
29497
29949
  sessionId: string()
29498
29950
  }), WebrtcSessionDebugSchema, { kind: "query" });
@@ -29732,6 +30184,59 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
29732
30184
  var RestartAddonResultSchema = unknown();
29733
30185
  var InstallPackageResultSchema = unknown();
29734
30186
  var ReloadPackagesResultSchema = unknown();
30187
+ /**
30188
+ * What an uninstall did on ONE node.
30189
+ * - `uninstalled` — removed: runner(s) stopped, caps gone, code deleted.
30190
+ * - `not-installed` — the node did not have it (nothing to do).
30191
+ * - `refused` — protected / bootstrap package; nothing touched.
30192
+ * - `failed` — attempted and did not complete; `error` says why.
30193
+ * - `pending-reconnect` — the node is OFFLINE: its record was pruned so the
30194
+ * back-fill never returns the package, and the stale-addon sweep removes the
30195
+ * copy when the node registers again (only once the hub no longer has it).
30196
+ */
30197
+ var UninstallNodeOutcomeSchema = _enum([
30198
+ "uninstalled",
30199
+ "not-installed",
30200
+ "refused",
30201
+ "failed",
30202
+ "pending-reconnect"
30203
+ ]);
30204
+ var UninstallNodeResultSchema = object({
30205
+ nodeId: string(),
30206
+ outcome: UninstallNodeOutcomeSchema,
30207
+ error: string().optional(),
30208
+ addonIds: array(string()).readonly(),
30209
+ runnersStopped: array(string()).readonly(),
30210
+ warnings: array(string()).readonly()
30211
+ });
30212
+ var UninstallPackageResultSchema = object({
30213
+ /** Every targeted node ended `uninstalled`, `not-installed` or `pending-reconnect`. */
30214
+ success: boolean(),
30215
+ packageName: string(),
30216
+ results: array(UninstallNodeResultSchema).readonly()
30217
+ });
30218
+ /**
30219
+ * `unreachable` lists online agents whose status read FAILED — absence from
30220
+ * `installations` is only "not installed" for a node that answered (D315).
30221
+ */
30222
+ var PackageInstallationsSchema = object({
30223
+ installations: array(object({
30224
+ packageName: string(),
30225
+ nodeId: string(),
30226
+ nodeName: string(),
30227
+ isHub: boolean(),
30228
+ isOnline: boolean(),
30229
+ version: string().nullable(),
30230
+ addonIds: array(string()).readonly(),
30231
+ source: _enum(["live", "recorded"]),
30232
+ /** The hub installs this package too. `false` on an agent row = an orphan. */
30233
+ onHub: boolean()
30234
+ })).readonly(),
30235
+ unreachable: array(object({
30236
+ nodeId: string(),
30237
+ error: string()
30238
+ })).readonly()
30239
+ });
29735
30240
  var BulkUpdateItemStatusSchema = _enum([
29736
30241
  "queued",
29737
30242
  "updating",
@@ -29814,10 +30319,14 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
29814
30319
  }), method(object({ packageName: string() }), InstallPackageResultSchema, {
29815
30320
  kind: "mutation",
29816
30321
  auth: "admin"
29817
- }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({ packageName: string() }), unknown(), {
30322
+ }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
30323
+ packageName: string().min(1),
30324
+ nodeId: string().optional(),
30325
+ everywhere: boolean().optional()
30326
+ }), UninstallPackageResultSchema, {
29818
30327
  kind: "mutation",
29819
30328
  auth: "admin"
29820
- }), method(_void(), ReloadPackagesResultSchema, {
30329
+ }), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
29821
30330
  kind: "mutation",
29822
30331
  auth: "admin"
29823
30332
  }), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
@@ -33304,7 +33813,8 @@ var ConnectionEndpointSchema = object({
33304
33813
  "lan-ipv6",
33305
33814
  "public",
33306
33815
  "loopback",
33307
- "app-link"
33816
+ "app-link",
33817
+ "custom"
33308
33818
  ]),
33309
33819
  /**
33310
33820
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -33373,7 +33883,7 @@ var GetConnectionEndpointsResultSchema = object({
33373
33883
  localPort: AdvertisedLocalPortSchema
33374
33884
  });
33375
33885
  /**
33376
- * The address flagged for notification links. `baseUrl: null` = AUTO, which
33886
+ * The address flagged for notification taps (`notificationTaps`). `baseUrl: null` = AUTO, which
33377
33887
  * since D709 is the CamStack app link; `resolved` reports the effective value,
33378
33888
  * so the UI can show it either way.
33379
33889
  */
@@ -33406,6 +33916,72 @@ var ViewerEndpointsSchema = object({
33406
33916
  /** What the ranking currently resolves to (may be empty if nothing is up). */
33407
33917
  resolved: array(string()).readonly()
33408
33918
  });
33919
+ /**
33920
+ * DEPRECATED compatibility shape of `getHubAddresses` (D729 amendment, kept
33921
+ * for addons built against it): `cluster` is the `internal` role, `browser`
33922
+ * the `publicEndpoint` role; `override` is the flagged address.
33923
+ */
33924
+ var HubAddressSnapshotSchema = object({
33925
+ override: string().nullable(),
33926
+ resolved: string().nullable(),
33927
+ source: _enum([
33928
+ "override",
33929
+ "auto",
33930
+ "none"
33931
+ ])
33932
+ });
33933
+ var HubAddressesSchema = object({
33934
+ cluster: HubAddressSnapshotSchema,
33935
+ browser: HubAddressSnapshotSchema
33936
+ });
33937
+ /**
33938
+ * What an address is used for (`hub-address.ts`, D734). `appConnections` is
33939
+ * many-valued; `notificationTaps`, `publicEndpoint` and `internal` are carried
33940
+ * by at most one address.
33941
+ */
33942
+ var HubAddressRoleSchema = _enum(HUB_ADDRESS_ROLES);
33943
+ var RoleSourceSchema = _enum([
33944
+ "flagged",
33945
+ "auto",
33946
+ "none"
33947
+ ]);
33948
+ /** One single-valued role: the flagged address, the one in use, and why. */
33949
+ var HubAddressRoleResolutionSchema = object({
33950
+ /** The address carrying the flag, or null = automatic. */
33951
+ flagged: string().nullable(),
33952
+ /** The address in use, or null when nothing qualifies (never loopback). */
33953
+ resolved: string().nullable(),
33954
+ source: RoleSourceSchema
33955
+ });
33956
+ var HubAppConnectionsResolutionSchema = object({
33957
+ /** The addresses flagged `appConnections`, or empty = automatic. */
33958
+ flagged: array(string()).readonly(),
33959
+ /** What the apps race right now. */
33960
+ resolved: array(string()).readonly(),
33961
+ source: RoleSourceSchema
33962
+ });
33963
+ var HubAddressBookSchema = object({
33964
+ rows: array(ConnectionEndpointSchema.extend({
33965
+ /** In the hub's detected palette right now. */
33966
+ detected: boolean(),
33967
+ /** Entered by the operator (removable). */
33968
+ custom: boolean(),
33969
+ /** The roles explicitly flagged on this address. */
33970
+ flags: array(HubAddressRoleSchema).readonly(),
33971
+ /** The roles this address serves right now — flagged or automatic. */
33972
+ inUse: array(HubAddressRoleSchema).readonly(),
33973
+ /** The roles this address may be flagged with. */
33974
+ eligible: array(HubAddressRoleSchema).readonly()
33975
+ })).readonly(),
33976
+ roles: object({
33977
+ appConnections: HubAppConnectionsResolutionSchema,
33978
+ notificationTaps: HubAddressRoleResolutionSchema,
33979
+ internal: HubAddressRoleResolutionSchema,
33980
+ publicEndpoint: HubAddressRoleResolutionSchema
33981
+ }),
33982
+ /** The `hub=` an app link carries (D709), or null. */
33983
+ appLinkHub: string().nullable()
33984
+ });
33409
33985
  var AllowedAddressesSchema = object({
33410
33986
  /**
33411
33987
  * Allowlist of interface addresses operators have explicitly opted
@@ -33449,10 +34025,27 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
33449
34025
  * tunnel always emits `https://` regardless. */
33450
34026
  scheme: _enum(["http", "https"]).optional(),
33451
34027
  /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
33452
- * an address notification links can be flagged with, not a hub
34028
+ * an address notification taps can be flagged with, not a hub
33453
34029
  * route. Default `false`: racers and rankers never see it. */
33454
34030
  includeAppLink: boolean().optional()
33455
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
34031
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(object({ scheme: _enum(["http", "https"]).optional() }).optional(), HubAddressBookSchema), method(object({
34032
+ baseUrl: string(),
34033
+ label: string().max(80)
34034
+ }), HubAddressBookSchema, {
34035
+ kind: "mutation",
34036
+ auth: "admin"
34037
+ }), method(object({ baseUrl: string() }), HubAddressBookSchema, {
34038
+ kind: "mutation",
34039
+ auth: "admin"
34040
+ }), method(object({
34041
+ role: HubAddressRoleSchema,
34042
+ baseUrl: string().nullable(),
34043
+ enabled: boolean(),
34044
+ acceptInsecureHttp: boolean().optional()
34045
+ }), HubAddressBookSchema, {
34046
+ kind: "mutation",
34047
+ auth: "admin"
34048
+ }), method(_void(), HubAddressesSchema), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
33456
34049
  kind: "mutation",
33457
34050
  auth: "admin"
33458
34051
  }), method(object({
@@ -33910,7 +34503,8 @@ var MotionStatusSchema = object({
33910
34503
  * writes this slice (not even a boot seed), and neither does the runner's
33911
34504
  * phase machine: its phase is "a session is attached" for every on-motion
33912
34505
  * session, not motion, and it now has its own `DetectionPhaseTransition`.
33913
- * A provider's `isDetected` answers from the hub's slice.
34506
+ * A provider's `isDetected` and `getStatus` answer from the hub's slice
34507
+ * (`hubMotionNativeProvider`).
33914
34508
  * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
33915
34509
  * imports) — the provider pushes both edges itself, from the upstream
33916
34510
  * system's own state change. That is the sensor's own fact.
@@ -40212,6 +40806,32 @@ var TotpStatusSchema = object({
40212
40806
  /** Null when no row exists OR the row is still pending confirmation. */
40213
40807
  confirmedAt: number().nullable()
40214
40808
  });
40809
+ /**
40810
+ * user-management — singleton capability for user accounts, API keys,
40811
+ * and scoped tokens.
40812
+ *
40813
+ * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
40814
+ * — the subset check on `setUserScopes` / `createScopedToken` is moot
40815
+ * because non-admins never reach these. If/when we open non-admin
40816
+ * delegation, structural caller-scope subset check goes inside the
40817
+ * provider.
40818
+ */
40819
+ var ExternalIdentitySchema = object({
40820
+ /** Login-method id of the provider instance, e.g. `auth-oidc/authentik`. */
40821
+ provider: string(),
40822
+ /** The IdP's stable subject (`sub`) for this account. */
40823
+ subject: string(),
40824
+ /** The verified `iss` of the IdP the identity was linked under — `sub` is unique only per issuer. */
40825
+ issuer: string(),
40826
+ userId: string(),
40827
+ /** What the IdP called the account at link time (username / email) — display only. */
40828
+ label: string().optional(),
40829
+ linkedAt: number()
40830
+ });
40831
+ var ExternalIdentityKeySchema = object({
40832
+ provider: string().min(1),
40833
+ subject: string().min(1)
40834
+ });
40215
40835
  method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
40216
40836
  kind: "mutation",
40217
40837
  auth: "admin",
@@ -40325,7 +40945,22 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
40325
40945
  userId: string(),
40326
40946
  username: string(),
40327
40947
  scopes: array(TokenScopeSchema)
40328
- }).nullable(), { access: "view" }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
40948
+ }).nullable(), { access: "view" }), method(object({ userId: string() }), array(ExternalIdentitySchema), { auth: "admin" }), method(ExternalIdentityKeySchema, object({
40949
+ userId: string(),
40950
+ issuer: string()
40951
+ }).nullable(), { auth: "admin" }), method(ExternalIdentityKeySchema.extend({
40952
+ userId: string(),
40953
+ issuer: string().min(1),
40954
+ label: string().optional()
40955
+ }), object({ success: literal(true) }), {
40956
+ kind: "mutation",
40957
+ auth: "admin",
40958
+ access: "create"
40959
+ }), method(ExternalIdentityKeySchema.extend({ userId: string() }), object({ success: boolean() }), {
40960
+ kind: "mutation",
40961
+ auth: "admin",
40962
+ access: "delete"
40963
+ }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
40329
40964
  kind: "mutation",
40330
40965
  auth: "admin",
40331
40966
  access: "delete"
@@ -41027,6 +41662,16 @@ var zoneRulesCapability = {
41027
41662
  durability: "restored"
41028
41663
  };
41029
41664
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
41665
+ Object.freeze({
41666
+ person: .5,
41667
+ vehicle: .5,
41668
+ animal: .5
41669
+ });
41670
+ Object.freeze({
41671
+ person: .65,
41672
+ vehicle: .65,
41673
+ animal: .65
41674
+ });
41030
41675
  /**
41031
41676
  * Accessory device helpers — shared across drivers.
41032
41677
  *
@@ -42751,6 +43396,12 @@ Object.freeze({
42751
43396
  addonId: null,
42752
43397
  access: "view"
42753
43398
  },
43399
+ "addons.listInstallations": {
43400
+ capName: "addons",
43401
+ capScope: "system",
43402
+ addonId: null,
43403
+ access: "view"
43404
+ },
42754
43405
  "addons.listJobs": {
42755
43406
  capName: "addons",
42756
43407
  capScope: "system",
@@ -43933,90 +44584,18 @@ Object.freeze({
43933
44584
  addonId: null,
43934
44585
  access: "create"
43935
44586
  },
43936
- "decoder.createSession": {
43937
- capName: "decoder",
43938
- capScope: "system",
43939
- addonId: null,
43940
- access: "view"
43941
- },
43942
- "decoder.destroySession": {
43943
- capName: "decoder",
43944
- capScope: "system",
43945
- addonId: null,
43946
- access: "delete"
43947
- },
43948
- "decoder.getFrame": {
43949
- capName: "decoder",
43950
- capScope: "system",
43951
- addonId: null,
43952
- access: "view"
43953
- },
43954
44587
  "decoder.getInfo": {
43955
44588
  capName: "decoder",
43956
44589
  capScope: "system",
43957
44590
  addonId: null,
43958
44591
  access: "view"
43959
44592
  },
43960
- "decoder.getShmStats": {
43961
- capName: "decoder",
43962
- capScope: "system",
43963
- addonId: null,
43964
- access: "view"
43965
- },
43966
- "decoder.getStats": {
43967
- capName: "decoder",
43968
- capScope: "system",
43969
- addonId: null,
43970
- access: "view"
43971
- },
43972
- "decoder.listActiveSessions": {
43973
- capName: "decoder",
43974
- capScope: "system",
43975
- addonId: null,
43976
- access: "view"
43977
- },
43978
- "decoder.openStream": {
43979
- capName: "decoder",
43980
- capScope: "system",
43981
- addonId: null,
43982
- access: "view"
43983
- },
43984
- "decoder.pullFrames": {
43985
- capName: "decoder",
43986
- capScope: "system",
43987
- addonId: null,
43988
- access: "view"
43989
- },
43990
- "decoder.pullHandles": {
43991
- capName: "decoder",
43992
- capScope: "system",
43993
- addonId: null,
43994
- access: "view"
43995
- },
43996
- "decoder.pushPacket": {
43997
- capName: "decoder",
43998
- capScope: "system",
43999
- addonId: null,
44000
- access: "view"
44001
- },
44002
44593
  "decoder.reprobeHwaccel": {
44003
44594
  capName: "decoder",
44004
44595
  capScope: "system",
44005
44596
  addonId: null,
44006
44597
  access: "create"
44007
44598
  },
44008
- "decoder.supportsCodec": {
44009
- capName: "decoder",
44010
- capScope: "system",
44011
- addonId: null,
44012
- access: "view"
44013
- },
44014
- "decoder.updateConfig": {
44015
- capName: "decoder",
44016
- capScope: "system",
44017
- addonId: null,
44018
- access: "view"
44019
- },
44020
44599
  "detectionPipeline.applyDeviceSettingsPatch": {
44021
44600
  capName: "detection-pipeline",
44022
44601
  capScope: "device",
@@ -45505,12 +46084,24 @@ Object.freeze({
45505
46084
  addonId: null,
45506
46085
  access: "view"
45507
46086
  },
46087
+ "localNetwork.addCustomAddress": {
46088
+ capName: "local-network",
46089
+ capScope: "system",
46090
+ addonId: null,
46091
+ access: "create"
46092
+ },
45508
46093
  "localNetwork.downloadCa": {
45509
46094
  capName: "local-network",
45510
46095
  capScope: "system",
45511
46096
  addonId: null,
45512
46097
  access: "view"
45513
46098
  },
46099
+ "localNetwork.getAddresses": {
46100
+ capName: "local-network",
46101
+ capScope: "system",
46102
+ addonId: null,
46103
+ access: "view"
46104
+ },
45514
46105
  "localNetwork.getAllowedAddresses": {
45515
46106
  capName: "local-network",
45516
46107
  capScope: "system",
@@ -45523,6 +46114,12 @@ Object.freeze({
45523
46114
  addonId: null,
45524
46115
  access: "view"
45525
46116
  },
46117
+ "localNetwork.getHubAddresses": {
46118
+ capName: "local-network",
46119
+ capScope: "system",
46120
+ addonId: null,
46121
+ access: "view"
46122
+ },
45526
46123
  "localNetwork.getNotificationEndpoint": {
45527
46124
  capName: "local-network",
45528
46125
  capScope: "system",
@@ -45559,6 +46156,12 @@ Object.freeze({
45559
46156
  addonId: null,
45560
46157
  access: "create"
45561
46158
  },
46159
+ "localNetwork.removeCustomAddress": {
46160
+ capName: "local-network",
46161
+ capScope: "system",
46162
+ addonId: null,
46163
+ access: "delete"
46164
+ },
45562
46165
  "localNetwork.resetAllowlistToBestMatch": {
45563
46166
  capName: "local-network",
45564
46167
  capScope: "system",
@@ -45571,6 +46174,12 @@ Object.freeze({
45571
46174
  addonId: null,
45572
46175
  access: "create"
45573
46176
  },
46177
+ "localNetwork.setAddressRole": {
46178
+ capName: "local-network",
46179
+ capScope: "system",
46180
+ addonId: null,
46181
+ access: "create"
46182
+ },
45574
46183
  "localNetwork.setAllowedAddresses": {
45575
46184
  capName: "local-network",
45576
46185
  capScope: "system",
@@ -47017,6 +47626,12 @@ Object.freeze({
47017
47626
  addonId: null,
47018
47627
  access: "create"
47019
47628
  },
47629
+ "pipelineAnalytics.setRetrainFrameComplete": {
47630
+ capName: "pipeline-analytics",
47631
+ capScope: "device",
47632
+ addonId: null,
47633
+ access: "create"
47634
+ },
47020
47635
  "pipelineAnalytics.setTrackFlags": {
47021
47636
  capName: "pipeline-analytics",
47022
47637
  capScope: "device",
@@ -47053,6 +47668,12 @@ Object.freeze({
47053
47668
  addonId: null,
47054
47669
  access: "delete"
47055
47670
  },
47671
+ "pipelineAnalytics.writeRetrainArchive": {
47672
+ capName: "pipeline-analytics",
47673
+ capScope: "device",
47674
+ addonId: null,
47675
+ access: "create"
47676
+ },
47056
47677
  "pipelineExecutor.cacheFrameInPool": {
47057
47678
  capName: "pipeline-executor",
47058
47679
  capScope: "system",
@@ -47065,13 +47686,13 @@ Object.freeze({
47065
47686
  addonId: null,
47066
47687
  access: "delete"
47067
47688
  },
47068
- "pipelineExecutor.deleteModel": {
47689
+ "pipelineExecutor.clearModelBoundDeviceOverrides": {
47069
47690
  capName: "pipeline-executor",
47070
47691
  capScope: "system",
47071
47692
  addonId: null,
47072
47693
  access: "delete"
47073
47694
  },
47074
- "pipelineExecutor.deleteTemplate": {
47695
+ "pipelineExecutor.deleteModel": {
47075
47696
  capName: "pipeline-executor",
47076
47697
  capScope: "system",
47077
47698
  addonId: null,
@@ -47215,12 +47836,6 @@ Object.freeze({
47215
47836
  addonId: null,
47216
47837
  access: "view"
47217
47838
  },
47218
- "pipelineExecutor.listTemplates": {
47219
- capName: "pipeline-executor",
47220
- capScope: "system",
47221
- addonId: null,
47222
- access: "view"
47223
- },
47224
47839
  "pipelineExecutor.rearmInferenceDevice": {
47225
47840
  capName: "pipeline-executor",
47226
47841
  capScope: "system",
@@ -47245,12 +47860,6 @@ Object.freeze({
47245
47860
  addonId: null,
47246
47861
  access: "create"
47247
47862
  },
47248
- "pipelineExecutor.saveTemplate": {
47249
- capName: "pipeline-executor",
47250
- capScope: "system",
47251
- addonId: null,
47252
- access: "create"
47253
- },
47254
47863
  "pipelineExecutor.setVideoPipelineSteps": {
47255
47864
  capName: "pipeline-executor",
47256
47865
  capScope: "system",
@@ -47269,41 +47878,35 @@ Object.freeze({
47269
47878
  addonId: null,
47270
47879
  access: "create"
47271
47880
  },
47272
- "pipelineExecutor.updateTemplate": {
47273
- capName: "pipeline-executor",
47274
- capScope: "system",
47275
- addonId: null,
47276
- access: "create"
47277
- },
47278
47881
  "pipelineExecutor.validatePipeline": {
47279
47882
  capName: "pipeline-executor",
47280
47883
  capScope: "system",
47281
47884
  addonId: null,
47282
47885
  access: "view"
47283
47886
  },
47284
- "pipelineOrchestrator.applyDeviceSettingsPatch": {
47887
+ "pipelineOrchestrator.applyAutoTune": {
47285
47888
  capName: "pipeline-orchestrator",
47286
47889
  capScope: "system",
47287
47890
  addonId: null,
47288
47891
  access: "create"
47289
47892
  },
47290
- "pipelineOrchestrator.assignAudio": {
47893
+ "pipelineOrchestrator.applyDeviceSettingsPatch": {
47291
47894
  capName: "pipeline-orchestrator",
47292
47895
  capScope: "system",
47293
47896
  addonId: null,
47294
47897
  access: "create"
47295
47898
  },
47296
- "pipelineOrchestrator.assignPipeline": {
47899
+ "pipelineOrchestrator.assignAudio": {
47297
47900
  capName: "pipeline-orchestrator",
47298
47901
  capScope: "system",
47299
47902
  addonId: null,
47300
47903
  access: "create"
47301
47904
  },
47302
- "pipelineOrchestrator.deleteTemplate": {
47905
+ "pipelineOrchestrator.assignPipeline": {
47303
47906
  capName: "pipeline-orchestrator",
47304
47907
  capScope: "system",
47305
47908
  addonId: null,
47306
- access: "delete"
47909
+ access: "create"
47307
47910
  },
47308
47911
  "pipelineOrchestrator.getAgentLoad": {
47309
47912
  capName: "pipeline-orchestrator",
@@ -47395,6 +47998,12 @@ Object.freeze({
47395
47998
  addonId: null,
47396
47999
  access: "view"
47397
48000
  },
48001
+ "pipelineOrchestrator.getEffectiveShares": {
48002
+ capName: "pipeline-orchestrator",
48003
+ capScope: "system",
48004
+ addonId: null,
48005
+ access: "view"
48006
+ },
47398
48007
  "pipelineOrchestrator.getGlobalMetrics": {
47399
48008
  capName: "pipeline-orchestrator",
47400
48009
  capScope: "system",
@@ -47431,19 +48040,19 @@ Object.freeze({
47431
48040
  addonId: null,
47432
48041
  access: "view"
47433
48042
  },
47434
- "pipelineOrchestrator.getReconcileFromDiskStatus": {
48043
+ "pipelineOrchestrator.getPlacementStats": {
47435
48044
  capName: "pipeline-orchestrator",
47436
48045
  capScope: "system",
47437
48046
  addonId: null,
47438
48047
  access: "view"
47439
48048
  },
47440
- "pipelineOrchestrator.listAgentSettings": {
48049
+ "pipelineOrchestrator.getReconcileFromDiskStatus": {
47441
48050
  capName: "pipeline-orchestrator",
47442
48051
  capScope: "system",
47443
48052
  addonId: null,
47444
48053
  access: "view"
47445
48054
  },
47446
- "pipelineOrchestrator.listTemplates": {
48055
+ "pipelineOrchestrator.listAgentSettings": {
47447
48056
  capName: "pipeline-orchestrator",
47448
48057
  capScope: "system",
47449
48058
  addonId: null,
@@ -47455,6 +48064,12 @@ Object.freeze({
47455
48064
  addonId: null,
47456
48065
  access: "create"
47457
48066
  },
48067
+ "pipelineOrchestrator.planAutoTune": {
48068
+ capName: "pipeline-orchestrator",
48069
+ capScope: "system",
48070
+ addonId: null,
48071
+ access: "view"
48072
+ },
47458
48073
  "pipelineOrchestrator.rebalance": {
47459
48074
  capName: "pipeline-orchestrator",
47460
48075
  capScope: "system",
@@ -47497,12 +48112,6 @@ Object.freeze({
47497
48112
  addonId: null,
47498
48113
  access: "create"
47499
48114
  },
47500
- "pipelineOrchestrator.saveTemplate": {
47501
- capName: "pipeline-orchestrator",
47502
- capScope: "system",
47503
- addonId: null,
47504
- access: "create"
47505
- },
47506
48115
  "pipelineOrchestrator.setAgentCapabilities": {
47507
48116
  capName: "pipeline-orchestrator",
47508
48117
  capScope: "system",
@@ -47515,12 +48124,6 @@ Object.freeze({
47515
48124
  addonId: null,
47516
48125
  access: "create"
47517
48126
  },
47518
- "pipelineOrchestrator.setAgentDetectWeight": {
47519
- capName: "pipeline-orchestrator",
47520
- capScope: "system",
47521
- addonId: null,
47522
- access: "create"
47523
- },
47524
48127
  "pipelineOrchestrator.setAgentInferenceDevices": {
47525
48128
  capName: "pipeline-orchestrator",
47526
48129
  capScope: "system",
@@ -47557,6 +48160,12 @@ Object.freeze({
47557
48160
  addonId: null,
47558
48161
  access: "create"
47559
48162
  },
48163
+ "pipelineOrchestrator.setCameraStepSettings": {
48164
+ capName: "pipeline-orchestrator",
48165
+ capScope: "system",
48166
+ addonId: null,
48167
+ access: "create"
48168
+ },
47560
48169
  "pipelineOrchestrator.setCameraStepToggle": {
47561
48170
  capName: "pipeline-orchestrator",
47562
48171
  capScope: "system",
@@ -47575,25 +48184,37 @@ Object.freeze({
47575
48184
  addonId: null,
47576
48185
  access: "create"
47577
48186
  },
48187
+ "pipelineOrchestrator.setLoadBalancingShares": {
48188
+ capName: "pipeline-orchestrator",
48189
+ capScope: "system",
48190
+ addonId: null,
48191
+ access: "create"
48192
+ },
47578
48193
  "pipelineOrchestrator.setPipelineDevicePin": {
47579
48194
  capName: "pipeline-orchestrator",
47580
48195
  capScope: "system",
47581
48196
  addonId: null,
47582
48197
  access: "create"
47583
48198
  },
47584
- "pipelineOrchestrator.unassignAudio": {
48199
+ "pipelineOrchestrator.setShareSource": {
47585
48200
  capName: "pipeline-orchestrator",
47586
48201
  capScope: "system",
47587
48202
  addonId: null,
47588
48203
  access: "create"
47589
48204
  },
47590
- "pipelineOrchestrator.unassignPipeline": {
48205
+ "pipelineOrchestrator.suggestShares": {
48206
+ capName: "pipeline-orchestrator",
48207
+ capScope: "system",
48208
+ addonId: null,
48209
+ access: "view"
48210
+ },
48211
+ "pipelineOrchestrator.unassignAudio": {
47591
48212
  capName: "pipeline-orchestrator",
47592
48213
  capScope: "system",
47593
48214
  addonId: null,
47594
48215
  access: "create"
47595
48216
  },
47596
- "pipelineOrchestrator.updateTemplate": {
48217
+ "pipelineOrchestrator.unassignPipeline": {
47597
48218
  capName: "pipeline-orchestrator",
47598
48219
  capScope: "system",
47599
48220
  addonId: null,
@@ -49033,12 +49654,6 @@ Object.freeze({
49033
49654
  addonId: null,
49034
49655
  access: "view"
49035
49656
  },
49036
- "streamBroker.pullFrameHandles": {
49037
- capName: "stream-broker",
49038
- capScope: "system",
49039
- addonId: null,
49040
- access: "view"
49041
- },
49042
49657
  "streamBroker.regenerateRtspToken": {
49043
49658
  capName: "stream-broker",
49044
49659
  capScope: "system",
@@ -49105,12 +49720,6 @@ Object.freeze({
49105
49720
  addonId: null,
49106
49721
  access: "create"
49107
49722
  },
49108
- "streamBroker.subscribeFrames": {
49109
- capName: "stream-broker",
49110
- capScope: "system",
49111
- addonId: null,
49112
- access: "create"
49113
- },
49114
49723
  "streamBroker.unassignProfile": {
49115
49724
  capName: "stream-broker",
49116
49725
  capScope: "system",
@@ -49123,12 +49732,6 @@ Object.freeze({
49123
49732
  addonId: null,
49124
49733
  access: "create"
49125
49734
  },
49126
- "streamBroker.unsubscribeFrames": {
49127
- capName: "stream-broker",
49128
- capScope: "system",
49129
- addonId: null,
49130
- access: "create"
49131
- },
49132
49735
  "streamCatalog.getCatalog": {
49133
49736
  capName: "stream-catalog",
49134
49737
  capScope: "device",
@@ -49423,18 +50026,36 @@ Object.freeze({
49423
50026
  addonId: null,
49424
50027
  access: "delete"
49425
50028
  },
50029
+ "userManagement.findUserByExternalIdentity": {
50030
+ capName: "user-management",
50031
+ capScope: "system",
50032
+ addonId: null,
50033
+ access: "view"
50034
+ },
49426
50035
  "userManagement.getTotpStatus": {
49427
50036
  capName: "user-management",
49428
50037
  capScope: "system",
49429
50038
  addonId: null,
49430
50039
  access: "view"
49431
50040
  },
50041
+ "userManagement.linkExternalIdentity": {
50042
+ capName: "user-management",
50043
+ capScope: "system",
50044
+ addonId: null,
50045
+ access: "create"
50046
+ },
49432
50047
  "userManagement.listApiKeys": {
49433
50048
  capName: "user-management",
49434
50049
  capScope: "system",
49435
50050
  addonId: null,
49436
50051
  access: "view"
49437
50052
  },
50053
+ "userManagement.listExternalIdentities": {
50054
+ capName: "user-management",
50055
+ capScope: "system",
50056
+ addonId: null,
50057
+ access: "view"
50058
+ },
49438
50059
  "userManagement.listOauthSessions": {
49439
50060
  capName: "user-management",
49440
50061
  capScope: "system",
@@ -49513,6 +50134,12 @@ Object.freeze({
49513
50134
  addonId: null,
49514
50135
  access: "create"
49515
50136
  },
50137
+ "userManagement.unlinkExternalIdentity": {
50138
+ capName: "user-management",
50139
+ capScope: "system",
50140
+ addonId: null,
50141
+ access: "delete"
50142
+ },
49516
50143
  "userManagement.updateUser": {
49517
50144
  capName: "user-management",
49518
50145
  capScope: "system",
@@ -49825,6 +50452,12 @@ Object.freeze({
49825
50452
  addonId: null,
49826
50453
  access: "create"
49827
50454
  },
50455
+ "webrtcSession.applyDownlinkProbe": {
50456
+ capName: "webrtc-session",
50457
+ capScope: "device",
50458
+ addonId: null,
50459
+ access: "create"
50460
+ },
49828
50461
  "webrtcSession.closeSession": {
49829
50462
  capName: "webrtc-session",
49830
50463
  capScope: "device",
@@ -51788,11 +52421,6 @@ Object.freeze({
51788
52421
  form: "single",
51789
52422
  optional: false
51790
52423
  }],
51791
- "decoder.createSession": [{
51792
- name: "deviceId",
51793
- form: "single",
51794
- optional: true
51795
- }],
51796
52424
  "detectionPipeline.applyDeviceSettingsPatch": [{
51797
52425
  name: "deviceId",
51798
52426
  form: "single",
@@ -53003,6 +53631,11 @@ Object.freeze({
53003
53631
  form: "single",
53004
53632
  optional: false
53005
53633
  }],
53634
+ "pipelineAnalytics.setRetrainFrameComplete": [{
53635
+ name: "deviceId",
53636
+ form: "single",
53637
+ optional: false
53638
+ }],
53006
53639
  "pipelineAnalytics.setTrackFlags": [{
53007
53640
  name: "deviceId",
53008
53641
  form: "single",
@@ -53023,6 +53656,11 @@ Object.freeze({
53023
53656
  form: "single",
53024
53657
  optional: false
53025
53658
  }],
53659
+ "pipelineExecutor.clearModelBoundDeviceOverrides": [{
53660
+ name: "deviceIds",
53661
+ form: "array",
53662
+ optional: true
53663
+ }],
53026
53664
  "pipelineExecutor.runPipeline": [{
53027
53665
  name: "deviceId",
53028
53666
  form: "single",
@@ -53128,6 +53766,11 @@ Object.freeze({
53128
53766
  form: "single",
53129
53767
  optional: false
53130
53768
  }],
53769
+ "pipelineOrchestrator.setCameraStepSettings": [{
53770
+ name: "deviceId",
53771
+ form: "single",
53772
+ optional: false
53773
+ }],
53131
53774
  "pipelineOrchestrator.setCameraStepToggle": [{
53132
53775
  name: "deviceId",
53133
53776
  form: "single",
@@ -53899,6 +54542,11 @@ Object.freeze({
53899
54542
  form: "single",
53900
54543
  optional: false
53901
54544
  }],
54545
+ "webrtcSession.applyDownlinkProbe": [{
54546
+ name: "deviceId",
54547
+ form: "single",
54548
+ optional: false
54549
+ }],
53902
54550
  "webrtcSession.closeSession": [{
53903
54551
  name: "deviceId",
53904
54552
  form: "single",
@@ -54128,6 +54776,8 @@ new Map(Object.entries({
54128
54776
  "detection-blind": "device-events",
54129
54777
  "node-online": "system",
54130
54778
  "node-offline": "system",
54779
+ "node-restarting": "system",
54780
+ "node-updating": "system",
54131
54781
  "node-inference-unavailable": "system",
54132
54782
  "addon-crash-loop": "system",
54133
54783
  "addon-update-available": "system",
@@ -54205,6 +54855,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
54205
54855
  kinds: [
54206
54856
  "node-offline",
54207
54857
  "node-online",
54858
+ "node-restarting",
54208
54859
  "node-inference-unavailable"
54209
54860
  ]
54210
54861
  },
@@ -54226,6 +54877,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
54226
54877
  label: "Server & container updates",
54227
54878
  kinds: [
54228
54879
  "server-update-available",
54880
+ "node-updating",
54229
54881
  "server-updated",
54230
54882
  "wrapper-update-available"
54231
54883
  ]
@@ -54373,6 +55025,7 @@ var STATE_SUMMARY_SECTION_VARS = [
54373
55025
  kinds: [
54374
55026
  "node-offline",
54375
55027
  "node-online",
55028
+ "node-restarting",
54376
55029
  "node-inference-unavailable"
54377
55030
  ]
54378
55031
  },
@@ -54394,6 +55047,7 @@ var STATE_SUMMARY_SECTION_VARS = [
54394
55047
  example: "server 1.2.377 → 1.2.378",
54395
55048
  kinds: [
54396
55049
  "server-update-available",
55050
+ "node-updating",
54397
55051
  "server-updated",
54398
55052
  "wrapper-update-available"
54399
55053
  ]
@@ -54426,7 +55080,7 @@ var STATE_SUMMARY_VARS = [
54426
55080
  {
54427
55081
  name: "summarySection",
54428
55082
  label: "Summary: this section",
54429
- description: "The section a per-section summary row is about (D698); on a summary sent as one message, every section it reports, comma-separated.",
55083
+ description: "The section a per-section summary row is about; on a summary sent as one message, every section it reports, comma-separated.",
54430
55084
  example: "Batterie scariche",
54431
55085
  group: "system",
54432
55086
  families: ["rule"],
@@ -54849,10 +55503,9 @@ TimelapseRuleInputSchema.extend({
54849
55503
  createdAt: number(),
54850
55504
  updatedAt: number()
54851
55505
  });
54852
- async function readHubMotionDetected(deviceState, deviceId) {
54853
- let slice;
55506
+ async function readSlice(deviceState, deviceId) {
54854
55507
  try {
54855
- slice = await deviceState.getCapSlice.query({
55508
+ return await deviceState.getCapSlice.query({
54856
55509
  deviceId,
54857
55510
  capName: "motion"
54858
55511
  });
@@ -54860,10 +55513,44 @@ async function readHubMotionDetected(deviceState, deviceId) {
54860
55513
  const reason = err instanceof Error ? err.message : String(err);
54861
55514
  throw new Error(`motion state of device ${deviceId} is unreadable: ${reason}`, { cause: err });
54862
55515
  }
54863
- const detected = slice?.["detected"];
55516
+ }
55517
+ /**
55518
+ * The hub's `motion` slice as a `MotionStatus`, or `null` when nobody has
55519
+ * published it since the hub started. Throws when the hub does not answer or
55520
+ * the slice is malformed — never a made-up "no motion".
55521
+ */
55522
+ async function readHubMotionStatus(deviceState, deviceId) {
55523
+ const slice = await readSlice(deviceState, deviceId);
55524
+ if (slice === null) return null;
55525
+ const parsed = MotionStatusSchema.safeParse(slice);
55526
+ if (!parsed.success) throw new Error(`motion state of device ${deviceId} is malformed on the hub: ${parsed.error.message}`);
55527
+ return parsed.data;
55528
+ }
55529
+ async function readHubMotionDetected(deviceState, deviceId) {
55530
+ const detected = (await readSlice(deviceState, deviceId))?.["detected"];
54864
55531
  if (typeof detected !== "boolean") throw new Error(`motion state of device ${deviceId} is not published yet (unknown)`);
54865
55532
  return detected;
54866
55533
  }
55534
+ /**
55535
+ * The native `motion` provider of a camera whose slice the orchestrator writes
55536
+ * (D696): `isDetected` AND `getStatus`, both from the hub. `owner` names the
55537
+ * provider class in the deviceId-mismatch error.
55538
+ */
55539
+ function hubMotionNativeProvider(deviceState, deviceId, owner) {
55540
+ const ownDevice = (asked) => {
55541
+ if (asked !== deviceId) throw new Error(`${owner}: motion deviceId mismatch, expected ${deviceId}, got ${asked}`);
55542
+ };
55543
+ return {
55544
+ isDetected: async ({ deviceId: asked }) => {
55545
+ ownDevice(asked);
55546
+ return readHubMotionDetected(deviceState, deviceId);
55547
+ },
55548
+ getStatus: async ({ deviceId: asked }) => {
55549
+ ownDevice(asked);
55550
+ return readHubMotionStatus(deviceState, deviceId);
55551
+ }
55552
+ };
55553
+ }
54867
55554
  MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
54868
55555
  function providerMotionEvent(source, data) {
54869
55556
  return createEvent(EventCategory.ProviderMotion, source, data);
@@ -156051,7 +156738,7 @@ function buildInitialStatus2(config, enabled) {
156051
156738
  * Node-only (`node:child_process`), so it lives under `@camstack/types/node`.
156052
156739
  */
156053
156740
  /** The detail a site refusing for want of a binary puts in its refusal. */
156054
- var NO_PINNED_FFMPEG_DETAIL = "no pinned ffmpeg on this node (D540)";
156741
+ var NO_PINNED_FFMPEG_DETAIL = "no pinned ffmpeg on this node";
156055
156742
  /**
156056
156743
  * {@link pinnedFfmpegSpawner}, asked at the point of use through the node's
156057
156744
  * resolver (`memoizePinnedFfmpeg`). A site that keeps the RESOLVER rather than
@@ -156191,7 +156878,7 @@ var reolinkCameraSchema = object({
156191
156878
  host: string().describe("Camera IP or hostname"),
156192
156879
  port: number().default(9e3).describe("Baichuan port (default 9000)"),
156193
156880
  username: string().default("admin").describe("Username"),
156194
- password: string().describe("Password"),
156881
+ password: string().describe("Password").meta({ secret: true }),
156195
156882
  /**
156196
156883
  * Transport mode resolved at creation time by autodetect (Slice 15).
156197
156884
  * - `tcp` : standard TCP-based Baichuan (regular cameras, NVR/Hub)
@@ -156872,7 +157559,7 @@ var reolinkHubSchema = object({
156872
157559
  host: string().describe("Hub IP or hostname"),
156873
157560
  port: number().default(9e3).describe("Baichuan port (default 9000)"),
156874
157561
  username: string().default("admin"),
156875
- password: string(),
157562
+ password: string().meta({ secret: true }),
156876
157563
  /** Hubs are TCP-only on supported firmwares — kept here for symmetry. */
156877
157564
  transport: _enum(["tcp", "udp"]).default("tcp"),
156878
157565
  /** UID is unused on Hubs (no UDP discovery), but persisted for symmetry. */
@@ -166983,16 +167670,14 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
166983
167670
  * `handleSimpleEvent` emits its raw push as `ProviderMotion` (`source:
166984
167671
  * 'onboard'`, D673), the orchestrator's camera-sensors bridge turns it into
166985
167672
  * the effective `MotionOnMotionChanged`, and the orchestrator is the slice's
166986
- * only writer, with that effective value, on the hub. `isDetected`
166987
- * therefore answers from the HUB's slice; an unreadable hub, or a slice
166988
- * nobody has published since the hub started, fails the call. It never
166989
- * answers `false` for "unknown" (D49, D393).
167673
+ * only writer, with that effective value, on the hub. `isDetected` AND
167674
+ * `getStatus` therefore answer from the HUB's slice
167675
+ * (`hubMotionNativeProvider`); an unreadable hub fails both. Never `false`
167676
+ * for "unknown" (D49, D393).
166990
167677
  */
166991
167678
  registerMotionCap() {
166992
- this.ctx.registerNativeCap(motionCapability, { isDetected: async ({ deviceId }) => {
166993
- if (deviceId !== this.id) throw new Error(`ReolinkCamera: deviceId mismatch, expected ${this.id}, got ${deviceId}`);
166994
- return readHubMotionDetected(this.ctx.api.deviceState, this.id);
166995
- } });
167679
+ const motionProvider = hubMotionNativeProvider(this.ctx.api.deviceState, this.id, "ReolinkCamera");
167680
+ this.ctx.registerNativeCap(motionCapability, motionProvider);
166996
167681
  }
166997
167682
  registerNetworkLink() {
166998
167683
  this.ctx.registerNativeCap(networkLinkCapability, { getStatus: async ({ deviceId }) => {